SEPA Direct Debit
Your account must be enabled for this feature
Limited to EMEA
Prerequisite
You have obtained and stored a valid SEPA mandate, hold a valid SEPA Creditor ID, and comply with applicable mandate retention and pre-notification requirements. More details: link
This guide explains how to submit one-off and recurring SEPA Direct Debit collections through the Payments REST API, interpret the response correctly, and follow the transaction through settlement.
Endpoint
Submit a primary SEPA transaction to:
POST {baseUrl}/payments
Use the base URL supplied for your environment. The public API reference currently lists:
One-off collection
Use SepaSaleTransaction with paymentMethod.sepa. The following request shows the minimum business data plus recommended merchant references:
{
"requestType": "SepaSaleTransaction",
"transactionAmount": {
"total": 49.90,
"currency": "EUR"
},
"transactionOrigin": "ECOM",
"merchantTransactionId": "SDD-20260827-0001",
"order": {
"orderId": "ORDER-20260827-0001"
},
"paymentMethod": {
"sepa": {
"iban": "<payer-iban>",
"name": "Max Mustermann",
"email": "[email protected]",
"mandate": {
"reference": "MANDATE-2026-0001",
"signatureDate": "2026-08-20",
"type": "SINGLE"
}
}
}
}
Request fields
| JSON path | Presence | Description |
|---|---|---|
requestType | Mandatory | Use SepaSaleTransaction for a SEPA Direct Debit collection. |
transactionAmount.total | Mandatory | Collection amount as a JSON number. |
transactionAmount.currency | Mandatory | Use EUR. |
transactionOrigin | Recommended | Use the origin agreed for the integration, normally ECOM for an online merchant flow. |
merchantTransactionId | Optional, recommended | Unique merchant reference, up to 40 characters, used for tracing and inquiry. |
order.orderId | Optional, recommended | Merchant order reference. The gateway generates an order ID when it is omitted. |
paymentMethod.sepa.iban | Mandatory | Payer's bank account in IBAN format, up to 34 characters. |
paymentMethod.sepa.name | Mandatory | Name of the payer/account holder, up to 96 characters. |
paymentMethod.sepa.email | Optional | Payer's email address, up to 254 characters. |
paymentMethod.sepa.mandate.reference | Mandatory | Merchant-managed mandate ID. It must be 1–35 permitted characters and must not begin with //. Reuse the same reference throughout a recurring series. |
paymentMethod.sepa.mandate.signatureDate | Mandatory | Date on which the payer originally approved the mandate, formatted as YYYY-MM-DD. This is not the collection submission date unless both events occurred on the same day. |
paymentMethod.sepa.mandate.type | Mandatory | SINGLE, FIRST_COLLECTION, RECURRING_COLLECTION, or FINAL_COLLECTION. |
paymentMethod.sepa.mandate.url | Conditional | URL to accessible mandate evidence. Include it when required by the configured SEPA Local Payments route or your onboarding agreement. |
storeId | Conditional | Outlet ID for applications authorized to submit transactions for multiple stores. |
Mandate sequence values
| Value | Use |
|---|---|
SINGLE | One collection only. |
FIRST_COLLECTION | First collection in a recurring series. |
RECURRING_COLLECTION | A subsequent collection under the same mandate. |
FINAL_COLLECTION | The final collection in the series. |
Do not create a new mandate reference or replace the original signature date for every recurring collection.
Response handling
The exact fields can vary by route and API release. A successful submission can return a response similar to this:
{
"type": "transactionResponse",
"clientRequestId": "87e8ee77-9fe8-41db-ae8e-e57d4a9c7f4c",
"apiTraceId": "<api-trace-id>",
"ipgTransactionId": "<ipg-transaction-id>",
"orderId": "ORDER-20260827-0001",
"transactionType": "SALE",
"transactionOrigin": "ECOM",
"approvedAmount": {
"total": 49.90,
"currency": "EUR"
},
"transactionResult": "APPROVED",
"transactionStatus": "APPROVED",
"approvalCode": "Y:<processor-code>:<transaction-reference>:<verification-result>:<endpoint-reference>",
"processor": {
"responseCode": "00",
"responseMessage": "Function performed error-free"
}
}
transactionStatus is deprecated. Prefer transactionResult when it is present.
Use the following decision logic:
const result = response.transactionResult ?? response.transactionStatus;
switch (result) {
case "APPROVED":
// Accepted for processing. Record the IDs and monitor the financial outcome.
break;
case "WAITING":
case "CREATED":
// Not final. Run transaction inquiry according to your retry policy.
break;
case "DECLINED":
case "FAILED":
case "FRAUD":
// Do not treat the collection as successful.
break;
case "PARTIAL":
// Do not assume that partial processing is valid for this SEPA flow.
// Review the returned amount and contact support if unexpected.
break;
default:
// Treat an unknown or absent result as unresolved, not approved.
}
Recurring collections with a payment token
For the first collection, use SepaSaleTransaction, set the mandate type to FIRST_COLLECTION, and request a reusable gateway token:
{
"requestType": "SepaSaleTransaction",
"transactionAmount": {
"total": 29.90,
"currency": "EUR"
},
"transactionOrigin": "ECOM",
"merchantTransactionId": "SDD-FIRST-20260827-0001",
"order": {
"orderId": "SUBSCRIPTION-10001-FIRST"
},
"paymentMethod": {
"sepa": {
"iban": "<payer-iban>",
"name": "Max Mustermann",
"email": "[email protected]",
"mandate": {
"reference": "MANDATE-SUBSCRIPTION-10001",
"signatureDate": "2026-08-20",
"type": "FIRST_COLLECTION"
}
}
},
"createToken": {
"reusable": true,
"declineDuplicates": false
}
}
Store the returned paymentToken.value securely. A token being present does not prove that the collection was approved or settled; evaluate the transaction result independently.
For a subsequent collection, use PaymentTokenSaleTransaction. Put the token and the mandate in the same paymentMethod object:
{
"requestType": "PaymentTokenSaleTransaction",
"transactionAmount": {
"total": 29.90,
"currency": "EUR"
},
"transactionOrigin": "ECOM",
"merchantTransactionId": "SDD-RECURRING-20260927-0001",
"order": {
"orderId": "SUBSCRIPTION-10001-2026-09"
},
"paymentMethod": {
"paymentToken": {
"value": "<payment-token>"
},
"sepaMandate": {
"reference": "MANDATE-SUBSCRIPTION-10001",
"signatureDate": "2026-08-20",
"type": "RECURRING_COLLECTION"
}
}
}
For the last scheduled collection, send the same structure with type: FINAL_COLLECTION.
Do not put sepaMandate inside paymentToken, and do not send a new signature date for later collections. Use the original mandate details.
Transaction inquiry and reconciliation
Retrieve the gateway's current transaction state using the ipgTransactionId returned by the original request:
GET {baseUrl}/payments/{ipgTransactionId}
You may also inquire by merchant transaction ID using the documented form:
GET {baseUrl}/payments/merchantTransactionId={merchantTransactionId}
Inquiry is especially important after a timeout, communication error, WAITING result, or any response whose outcome is unclear. Do not create a second debit with a new identifier until you have checked whether the first request was accepted.
Voids, refunds, and credits
Use a linked operation whenever you are reversing an existing collection.
Void before processing completes
POST {baseUrl}/payments/{ipgTransactionId}
{
"requestType": "VoidTransaction"
}
A void is possible only while the transaction and configured route still permit cancellation. Do not assume that a same-day request is always voidable; inspect the response.
Return an existing collection
POST {baseUrl}/payments/{ipgTransactionId}
{
"requestType": "ReturnTransaction",
"transactionAmount": {
"total": 29.90,
"currency": "EUR"
}
}
The permitted amount and timing depend on the original transaction and current state.
Unlinked SEPA credit transfer
Your account must be enabled for this feature
SepaCreditTransaction sends money to an IBAN without referencing an original collection. It is sometimes called a naked credit and normally requires explicit enablement.
{
"requestType": "SepaCreditTransaction",
"transactionAmount": {
"total": 12.76,
"currency": "EUR"
},
"transactionOrigin": "ECOM",
"merchantTransactionId": "SDD-CREDIT-20260827-0001",
"paymentMethod": {
"sepa": {
"iban": "<beneficiary-iban>",
"name": "Max Mustermann"
}
}
}
Do not use an unlinked credit as a substitute for a linked return unless this has been agreed during onboarding.
Updated 25 days ago