Server-to-Server
Collect the customer's MB WAY phone number in your own checkout, then send the payment request directly to the API. The customer approves the payment in the MB WAY app. There is no hosted page and no browser redirection.
For the full sequence diagram and status table, see Payment workflow on the MB WAY overview.
Implementation flow
- Ask the customer for the mobile phone number linked to their MB WAY account.
- Make a Payment API request with
payment_type: "mbway"and thephone. The synchronous response returns the transaction in thestartedstatus, and the customer receives a push notification in the MB WAY app. - Tell the customer to open the MB WAY app and approve the payment.
- When the customer approves or rejects the request, or does not answer in time, the transaction reaches its final status and a postback is sent.
A postback is sent on each status change, so use it, not the synchronous response, as the source of truth for the final result.
For a general walkthrough of credentials, authentication, and postbacks, see Get Started — Server-to-Server Processing.
Create a payment
POST/rest/payment
/rest/paymentProduction URL
https://api.betterpayment.de/rest/paymentTest URL
https://testapi.betterpayment.de/rest/paymentpayment_typeStringrequiredmbwayorder_idStringrequiredamountFloatrequiredcurrencyStringrequiredEURphoneStringrequired+4917143214321, 0049 171 43214321), or a Portuguese one without country code (912345678). It is converted to the MB WAY format <country code>#<number> automatically; numbers already in that format (34#612345678) are accepted too. Spaces, dashes and brackets are ignored. Other values are rejected with error code 166postback_urlStringrequiredPOST /rest/payment
Authorization: Basic <base64(api_key:api_password)>
Content-Type: application/json
{
"payment_type": "mbway",
"order_id": "MBWAY-12345",
"amount": "10.00",
"currency": "EUR",
"phone": "+351912345678",
"first_name": "Maria",
"last_name": "Silva",
"postback_url": "https://your-postback.url.com"
}
Payment API Response
transaction_idStringpayment_typeStringstatus_codeInteger1 (started) while the customer has not approved the payment yetstatusStringorder_idStringmessageStringamountFloaterror_codeInteger{
"transaction_id": "8d0c3a1e-6c1f-4e7e-9d8e-0b7a4f7f2c11",
"payment_type": "mbway",
"status_code": 1,
"status": "started",
"order_id": "MBWAY-12345",
"message": null,
"additional_transaction_data": null,
"amount": 10.0,
"recurring": 0,
"included_fees": "0.00",
"error_code": 0
}
If SIBS declines the request straight away (for example, because the phone number has no MB WAY account), the transaction is declined (6) and the response carries error code 108 with the reason in error_message.
The customer has about 4 minutes to approve the request in the MB WAY app. If they reject it, or do not answer in time, the payment becomes declined (6), sent by postback. The postback's message carries SIBS's reason, for example E0500: Operation was not accepted by the card holder for an unanswered request.
Authorize and capture
To reserve the amount first and charge it later, send the same request to POST /rest/authorize. After the customer approves it in the app, the transaction becomes authorized (8) and a postback is sent.
- Capture with
POST /rest/capture. You can capture the full amount or a smalleramountonce. The capture closes the authorisation: the uncaptured rest can't be captured or reversed afterwards. The transaction becomescompleted(3), and the capture postback carriesamount,captured_amountandcurrency. - Reverse with
POST /rest/reverseto release an authorisation you will not capture. The transaction becomesreversed(12).
If SIBS accepts a capture or reversal but has not finished it yet, the transaction stays authorized and the result follows by postback.
MB WAY mandates
An MB WAY mandate lets you charge the customer later without a new approval in the app, for example for subscriptions. The customer approves the mandate once in the MB WAY app and sets a monthly amount limit and an expiry date there.
Create a mandate
Create the mandate with the Mandate Reference API and payment_type: "mbway". Unlike SEPA mandate references, an MB WAY mandate request must be authenticated with Basic authentication or a checksum, because it sends an approval request to the customer's phone.
payment_typeStringrequiredmbwayphoneStringrequiredfirst_nameStringlast_namelast_nameStringpostback_urlStringrequiredPOST /rest/create_mandate_reference
Authorization: Basic <base64(api_key:api_password)>
Content-Type: application/json
{
"payment_type": "mbway",
"phone": "912345678",
"first_name": "Maria",
"last_name": "Silva",
"postback_url": "https://your-postback.url.com"
}
transaction_idStringoriginal_transaction_id when you charge the mandatestatus_codeInteger2 (pending) until the customer approves the mandate, then 9 (registered)mbway_mandate_statusStringpending, active, suspended, expired or cancelled{
"transaction_id": "1f7b2c4d-93a8-4b6e-a3f0-5d2e8c9b7a61",
"payment_type": "mbway",
"status_code": 2,
"status": "pending",
"order_id": null,
"message": "Waiting for the customer to approve the MB WAY mandate.",
"amount": 0.0,
"recurring": 0,
"mbway_mandate_status": "pending",
"token": null,
"error_code": 0
}
When the customer approves the mandate, it becomes registered (9) and a postback is sent with the mandate details:
{
"transaction_id": "1f7b2c4d-93a8-4b6e-a3f0-5d2e8c9b7a61",
"payment_type": "mbway",
"status_code": "9",
"status": "registered",
"mbway_mandate_status": "active",
"mbway_mandate_amount_limit": "50.0",
"mbway_mandate_expires_on": "2027-09-30"
}
The mandate's statuses:
| Status | Status Code | mbway_mandate_status | When |
|---|---|---|---|
pending | 2 | pending | Mandate created. Waiting for the customer to approve it in the app |
registered | 9 | active | The customer approved the mandate. It can be charged |
registered | 9 | suspended | The customer suspended the mandate in the app. Charges are rejected until they reactivate it |
canceled | 5 | cancelled or expired | The customer cancelled the mandate, or SIBS reported it expired |
declined | 6 | — | The customer rejected the mandate, or SIBS declined it |
A postback is sent on each change, including a suspension or reactivation. A mandate past its mbway_mandate_expires_on date is not charged (error code 164), even while it still shows as registered.
Recurring payments
Charge an approved mandate with a normal Payment API request, recurring: 1 and original_transaction_id set to the mandate's transaction_id. The phone is not needed. The customer does not have to approve the charge. Each charge is a new transaction; an original_transaction_id that is not an MB WAY mandate (for example an earlier payment) is rejected with error code 118.
{
"payment_type": "mbway",
"order_id": "MBWAY-SUB-2026-10",
"amount": "9.99",
"currency": "EUR",
"recurring": 1,
"original_transaction_id": "1f7b2c4d-93a8-4b6e-a3f0-5d2e8c9b7a61",
"postback_url": "https://your-postback.url.com"
}
The charge is usually completed (3) in the synchronous response. If SIBS is still processing it, it is started (1) and the result follows by postback.
A charge is rejected with one of these error codes:
| Error Code | Reason |
|---|---|
| 162 | original_transaction_id is not an MB WAY mandate |
| 163 | The customer has not approved the mandate yet |
| 164 | The mandate is suspended, cancelled or expired |
| 165 | The amount is above the mandate's monthly limit (this charge alone, or the total charged this month) |
The limit applies to the total charged per month. A single charge above it is rejected right away. A charge that would exceed what is left of it this month is declined by SIBS: the request also returns 165, and the payment becomes declined (6) with SIBS's reason in message.
Refund API
Refunds of completed payments are supported in full and in part.
POST/rest/refund
/rest/refundProduction URL
https://api.betterpayment.de/rest/refundTest URL
https://testapi.betterpayment.de/rest/refundtransaction_idStringrequiredamountFloatcommentStringPOST /rest/refund
Authorization: Basic <base64(api_key:api_password)>
Content-Type: application/json
{
"transaction_id": "8d0c3a1e-6c1f-4e7e-9d8e-0b7a4f7f2c11",
"amount": "4.00",
"comment": "Goods returned"
}
The refund is usually successful right away (status_code 1). If SIBS is still processing it, it is created as started (0) and the result is sent by postback with refund_status_code.
Postbacks
A postback is sent to your postback_url on each status change. MB WAY payments use the standard Payment API postback fields. Postbacks for an MB WAY mandate also include mbway_mandate_status, mbway_mandate_amount_limit and mbway_mandate_expires_on. For retry policy and signature verification, see Postbacks.
Test Data
In the test environment, MB WAY requests are sent to the SIBS test platform. To approve a payment you need a phone number registered in the SIBS test MB WAY app. Any other Portuguese mobile number (for example 912345678) is declined straight away, which you can use to test the declined flow.