SEPA Direct Debit
Description
SEPA Direct Debit lets you collect euro payments directly from a payer's bank account within the Single Euro Payments Area (SEPA). The payer authorises the collection by granting a SEPA mandate, which you must present at checkout and which the payer must accept before the payment is created.
This payment method supports both SEPA schemes:
ddfor the consumer (B2C) schemedd_b2bfor the business-to-business (B2B) scheme
There is no hosted page and no browser redirection. The transaction is submitted to the payer's financial institution during the next export cycle, so it stays in the started status until submission happens, and its final status is delivered asynchronously via postback.
Availability
Available for bank accounts denominated in EUR within the SEPA zone.
For the B2B scheme, the payer must be a business and the debtor's bank must support SEPA B2B collections.
Transaction Types
The following transaction types are currently available:
- Payment
- Refund (Full and partial refund, referenced)
- Payout (Unreferenced credit transfer to a bank account)
- Recurring Payments
Payment Flow
The transaction moves through the following statuses (identical for B2C and B2B). The Status Code column is the transaction's status code:
| Status | Status Code | When |
|---|---|---|
started | 1 | Payment created; queued for the next SEPA export cycle |
pending | 2 | Collection submitted to the bank via the export file. Treated as a successful state |
completed | 3 | The debit settled and no return was received |
chargeback | 13 | The collection was returned (a return with or without a reason code) |
declined | 6 | Return with a decline reason code |
error | 4 | Return with an error reason code |
The started status in the synchronous response is not the final result. SEPA is processed asynchronously, so use the postbacks sent on each status change as the source of truth. A standalone mandate reference created with the Mandate Reference API stays in the registered (9) status.
Legal Implications
Before creating an initial SEPA Direct Debit payment you must display the SEPA mandate information to the payer and have them explicitly agree to the collection of the debited amount. The mandate text must include the creditor details, the mandate reference, the account holder, and the IBAN.
For B2C, the payer has the right to demand a refund of a charged amount for up to eight weeks from the date of the charge. For B2B, there is no refund right for authorised collections after the debit. All examples of SEPA legal texts are provided for guidance only and are not guaranteed to be legally compliant.
For recurring collections, the payer must additionally receive a pre-notification announcing the amount and the due date before each collection.
API Implementation
Supported payment_type values:
ddfor SEPA Direct DebitB2Cdd_b2bfor SEPA Direct DebitB2B
Implementation Flow
Collect the payer's IBAN and mandate acceptance in your own checkout, then send the payment request directly to the API. There is no hosted page and no browser redirection. You can provide the mandate reference in one of three ways:
- pass your own reference in the
sepa_mandateparameter, - create one upfront with the Mandate Reference API and pass the returned
tokenassepa_mandate, or - omit
sepa_mandateand let the API generate one automatically.
Steps:
- Present the SEPA mandate at checkout and capture the payer's agreement.
- Make a Payment API request including the bank account data (
iban,account_holder) and the relevantpayment_type(ddordd_b2b). The synchronous response returns the transaction in thestartedstatus. - The collection is queued for the next SEPA export cycle. Once it is submitted to the bank, the transaction moves to
pendingand a postback is sent. - After the bank reconciles the collection, the transaction reaches its final status (
completed, orchargeback/declined/erroron a return), and a postback is sent for the change.
A postback is sent on each status change, so use it, not the synchronous response, as the source of truth for the final result.
Payment API
Payment API Request
The request structure is the same for both schemes. Only the payment_type value changes:
ddforB2Cdd_b2bforB2B
payment_typeStringrequireddd for B2C or dd_b2b for B2Border_idStringrequiredamountFloatrequiredcurrencyStringrequiredEURaccount_holderStringrequiredibanStringrequiredbicStringsepa_mandateStringpostback_urlStringrequiredPOST /rest/payment
Authorization: Basic <base64(api_key:api_password)>
Content-Type: application/json
{
"payment_type": "dd",
"order_id": "SEPA-12345",
"amount": "15.90",
"currency": "EUR",
"account_holder": "Max Mustermann",
"iban": "DE89370400440532013000",
"first_name": "Max",
"last_name": "Mustermann",
"address": "Teststr. 5",
"city": "Berlin",
"postal_code": "15557",
"country": "DE",
"postback_url": "https://your-postback.url.com"
}
For a B2B payment, use the same payload with payment_type: "dd_b2b". Example:
{
"payment_type": "dd_b2b",
"order_id": "SEPA-B2B-12345",
"amount": "150.00",
"currency": "EUR",
"account_holder": "Muster GmbH",
"iban": "DE89370400440532013000",
"first_name": "Max",
"last_name": "Mustermann",
"address": "Teststr. 5",
"city": "Berlin",
"postal_code": "15557",
"country": "DE",
"postback_url": "https://your-postback.url.com"
}
Payment API Response
The synchronous response format is the same for both schemes:
transaction_idStringpayment_typeStringstatus_codeInteger1 (started) until the collection is submitted to the bankstatusStringorder_idStringmessageStringadditional_transaction_dataStringpostback_url as part of the postback data.amountFloatincluded_feesStringerror_codeIntegermandate_idStringibanStringrecurring_mandateInteger1 if the mandate is recurring, 0 otherwiseexecution_dateString{
"transaction_id": "6c2e7e30-b741-4c5e-bc50-91dffdf0e5fb",
"payment_type": "dd",
"status_code": 1,
"status": "started",
"order_id": "SEPA-12345",
"message": null,
"additional_transaction_data": null,
"amount": 15.9,
"included_fees": "0.00",
"error_code": 0,
"mandate_id": "a7678918bfbbfa449cf9ff78446b60a4",
"iban": "DE89370400440532013000",
"recurring_mandate": 0,
"execution_date": "2026-07-07"
}
Depending on your payment method configuration and acquirer, SEPA transactions are submitted to the financial institution either the same day or the next business day. Until submission happens on our side, the transaction stays in the started state. Use the postback as the source of truth for the final status.
Create a Mandate Reference
SEPA Direct Debit transactions depend on a mandate. You can either provide the mandate yourself via the sepa_mandate parameter in the Payment API, or create a mandate reference upfront using the Mandate Reference API.
Use the dedicated API reference page for:
- the endpoint definition for
POST /rest/create_mandate_reference - request and response examples
- the full parameter list
- how to use the returned
transaction_idand mandate reference (tokenin the response, the value to show to the payer and to send later assepa_mandate)
When creating the mandate reference, use payment_type: "dd" for B2C or payment_type: "dd_b2b" for B2B.
Recurring Payments
Mandates can be one-time or recurring. For recurring collections:
- Create an initial payment or a mandate reference with
recurring: 1. - Store the returned
transaction_id. - Create each subsequent collection with
recurring: 1andoriginal_transaction_idset to the storedtransaction_id.
The recurring flow is the same for both schemes.
Refund API
Refunds are supported in full and in part. A SEPA refund is processed as a credit transfer back to the payer's account, so the refund is created in the started status and completed asynchronously.
transaction_idStringrequiredamountFloatcommentStringPOST /rest/refund
Authorization: Basic <base64(api_key:api_password)>
Content-Type: application/json
{
"transaction_id": "6c2e7e30-b741-4c5e-bc50-91dffdf0e5fb",
"amount": "15.90",
"comment": "Goods returned"
}
For B2B, note that the lack of payer refund rights for authorised collections does not change the merchant-side refund API flow.
Payout API
Payouts send money to a bank account without a prior payment (an unreferenced credit transfer). Provide the recipient bank account data.
payment_typeStringrequireddd for B2C or dd_b2b for B2Border_idStringrequiredamountFloatrequiredcurrencyStringrequiredaccount_holderStringrequiredibanStringrequiredmerchant_referenceStringpostback_urlStringrequiredPOST /rest/payout
Authorization: Basic <base64(api_key:api_password)>
Content-Type: application/json
{
"payment_type": "dd",
"order_id": "PAYOUT-12345",
"amount": "15.90",
"currency": "EUR",
"account_holder": "Max Mustermann",
"iban": "DE89370400440532013000",
"merchant_reference": "Refund for order XYZ",
"postback_url": "https://your-postback.url.com"
}
Postbacks
When the collection is submitted and its status changes, a postback is sent to your postback_url. In addition to the standard Payment API postback fields, SEPA Direct Debit postbacks include mandate_id, iban, bic, recurring_mandate, and execution_date. This applies to both B2C and B2B. For retry policy and signature verification, see Postbacks.
Test Data
Use the following test bank account in the sandbox environment for both B2C and B2B:
| Field | Value |
|---|---|
account_holder | Max Mustermann |
iban | DE89370400440532013000 |
bic | COBADEFFXXX |