Sepa Direct Debit (SDD OUT)
SEPA Direct Debit (SDD) is a pull-based payment scheme that allows a creditor to debit a debtor's bank account.
Similarly to other SEPA transfers, an SDD requires the IBAN (and occasionally the BIC) of both the sender and the recipient's bank accounts.
However, it differs from other SEPA transfers in that the roles are reversed: the recipient of the funds is the one who must request the money transfer from the sender.
SEPA Direct Debit is only available in Euros and can be used for both one-off transactions and recurring payments. It is often used for recurrent payments so that customers can avoid missing payments and being charged additional fees.
The debtor must sign a valid SDD mandate to authorize the creditor to withdraw the money from the debtor's account. Additionally, there are other rules governing SDDs, such as pre-notifications, refunds, returns, etc.
Xpollens provides a complete solution to create mandates and manage Sepa Direct Debit (SDD). If you already have a Sepa Creditor ID (SCI), you will be able to use it to direct debit your customer. If not, we can provide you with one within 48 hours.
General sequence diagram
sequenceDiagram
Title: Create an SDD Out (Core & B2B)
autoNumber
Actor User
Participant Partner
Participant XPO
Note over Partner, XPO: Create a beneficiary
Partner ->> XPO : POST api/sca/v2.0/users/appUserId/beneficiary
XPO ->> Partner : http 20X
Note over Partner, XPO: Create a mandate
Partner ->> XPO : POST /api/v2.0/accounts/accountId/mandates {beneficiaryId]
XPO ->> Partner : http 20X
XPO -->> Partner: webhook MandateCreatedOrUpdated
Partner -->> User: Sign the mandate
User -->> Partner: Signature
Note over Partner, XPO: Activate the mandate
Partner ->> XPO : POST /api/v2.0/accounts/accountId/mandates/{mandateId}/activate
XPO ->> Partner : http 20X
XPO -->> Partner: webhook MandateCreatedOrUpdated
Note over Partner, XPO: Create an SDD OUT
Partner ->> XPO : POST /api/v2.0/sepa-direct-debits
XPO ->> Partner : http 20X
XPO -->> Partner: webhook SepaDirectDebitCreatedOrUpdated (status: Created)
XPO -->> Partner: webhook SepaDirectDebitCreatedOrUpdated (status: Approved)
Note over Partner, XPO: Completion of the SDD on the settlement date
XPO -->> Partner: webhook SepaDirectDebitCreatedOrUpdated (status: Completed)
Mandate
The mandate creation is a prerequesite to create an SDD (see "State diagram for an SDD OUT").
State diagram for a debtor mandate (Core & B2B)
stateDiagram
[*] --> Created : when created
Created --> Activated: when activated
Created --> Revoked : when revoked
Activated --> Revoked : when revoked
Revoked --> [*]
Xpollens does not create a document for the mandate.If you want to display a document to your customers, you must create it.
Mandate creation
The prerequesite to create a mandate is to create the beneficiary.
sequenceDiagram
Title: Create a mandate (Core & B2B)
autoNumber
Actor User
Participant Partner
Participant XPO
Note over Partner, XPO: Create a beneficiary
Partner ->> XPO : POST api/sca/v2.0/users/appUserId/beneficiary
XPO ->> Partner : http 20X
Note over Partner, XPO: Create a mandate
Partner ->> XPO : POST /api/v2.0/accounts/{accountId}/mandates {beneficiaryId, type}
XPO ->> Partner : http 20X {mandateId}
XPO -->> Partner: webhook MandatedCreatedOrUpdated
To use this mandate and create and SDD, the mandate must be activated.
Mandate activation
sequenceDiagram
Title: Activate the mandate
autoNumber
Actor User
Participant Partner
Participant XPO
Note over Partner, XPO: Create a mandate
Partner -->> User: Sign the mandate
User -->> Partner: Signature
Note over Partner, XPO: Activate the mandate
Partner ->> XPO : POST /api/v2.0/accounts/{accountId}/mandates/{mandateId}/activate
XPO ->> Partner : http 20X
Mandate revocation
Why and when
The mandate can not be modified. As a consequence, if a modification is needed, you must :
- revoke the mandate
- create a new one
Impacts
The revocation of the mandate does not cancel already scheduled SDDs.
What happens if the end user revokes the mandate from their external bank?
Xpollens is not aware that all SDDs have been opposed and that the mandate has been revoked.However, we receive rejections for all direct debit attempts.
Sepa Direct Debit OUT (SDD OUT)
An SDD out is an SDD that debits an external account to credit the Xpollens account.
State diagram for an SDD OUT
stateDiagram-v2
[*] --> Created : internal status
Created --> Approved : http 201
Created --> Rejected: rejected by The Payment Decision System
Approved --> Rejected : /- rejected by BPCE <br/> /- rejected by the Interbank_market <br/> /- rejected by the external bank
Approved --> Completed : accepted
Rejected --> [*]
Completed --> [*]
Sequence diagram for an SDD OUT
sequenceDiagram
Title: Create an SDD
autoNumber
Actor User
Participant Partner
Participant XPO
Participant BPCE
Participant Interbank_market
Note over Partner, XPO: Create an SDD OUT
Partner ->> XPO : POST /api/v2.0/sepa-direct-debits
XPO ->> BPCE: create SDD
XPO -->> Partner: webhook SepaDirectDebitCreatedOrUpdated {status Approved}
Note over XPO, Interbank_market: Every working day 21h (FR)
BPCE -->> XPO : SDDs sent {executionDate}
XPO -->> Interbank_market: SDD sent
Note over Partner, Interbank_market: On the executionDate
XPO -->> Partner: webhook SepaDirectDebitCreatedOrUpdated {status Completed}
expectedExecutionDate
The expectedExecutionDate is the payment date expected by the partner (or its enduser) and entered in the request POST.
When the SDD creation on the SEPA exchange plateform, the expected execution date is recalculated. The value (new or not) is integrated in our system, and returns by the GET sdd. As a consequence, this date can evolve.
The expectedExecutionDate changes if the expectedExecutionDate is a day during a week-end or a day off. In this case, the expectedExecutionDate is the next working day.
Note: theexpectedExecutionDatecan not be in the past.An SDD can only be created a maximum of 14 days before the
expectedExecutionDate.
Therefore, you need to manage the debit schedule on your side to create the SDDs in a timely manner.
Rules
To schedule multiple SDDs in parallel for the same mandate, the first SDD must be finalized.This occurs as soon as its status changes to "Completed".
SDD Core vs. SDD B2B
1- The characteristic is defined during the mandate creation, through the type = Core or B2B
2- This information is replicated during the SDD creation, same attribute type
Rules are different according to the sdd type:
| SDD core | SDD B2B | |
|---|---|---|
| Uses | Consumer subscriptions Telecoms, energy, insurance, subscriptions, associations, etc. | Business-to-business commercial relationships Large or sensitive recurring B2B payments |
| Debtor profile | Individuals and companies | Companies only |
| Mandate validity requirements | Mandate signed by the debtor & mandate declared by the creditor to their bank | Mandate signed by the debtor & mandate declared by the creditor to their bank & mandate declared and validated by the debtor with their bank |
| Right to refund | 8 weeks without reason (from the due date) 13 months if no mandate (from the due date) | No refund possible, even within 8 weeks (from the due date) |
| Maximum presentation deadline | 14 days before the due date (settlement date) | 14 days before the due date (settlement date) |
| Creditor advantages | Universal (individuals + companies) Simple to implement (no obligation for the debtor to register and validate the mandate) | Reduced risk of post-debit non-payment: no refunds |
| Creditor disadvantages | Higher risk of post-debit non-payment | More complex to implement (the mandate must be registered and validated at the debtor’s bank) |
| Debtor advantages | Strong protection: right to a refund (within 8 weeks) | / |
| Debtor disadvantages | / | Obligation to register the mandate No recourse after the debit |
API & technical items
Error for a mandate creation
POST /api/v2.0/users/appuserId/mandates
| Use case | HTTP code | Code | Response |
|---|---|---|---|
| Wrong account | 404 | 147 | "Code": 147, "ErrorMessage": "The account accountId does not exist", "Title": "The operation cannot succeed", "Priority": 2, "Date": "2026-01-19T15:12:19.2722244", "OperationId": "ad0024bb182bfef80b604d3bbc7a0bed" |
| Beneficiary does not exist | 404 | 20002 | "Code": 20002, "ErrorMessage": "The beneficiary xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx does not exist", "Title": "The operation cannot succeed", "Priority": 2, "Date": "2026-01-19T15:13:51.8055949", "OperationId": "7d88eaa94c07a96738e28d6722aca127" |
| Missing attribute | 500 | 1 | "Code": 1, "ErrorMessage": "Une erreur technique est survenue, veuillez réessayer. Si l'erreur persiste, contactez le support client S-money. Object reference not set to an instance of an object.", "Title": "Erreur technique", "Priority": 2, "Date": "2026-01-19T15:16:13.9885186", "OperationId": "69eb472d4a63edfd5f9e13372aa1fa5a", "ErrorDetails": null |
| Incorrect mandate type | 400 | 715 | "Code": 715, "ErrorMessage": "Paramètre(s) d'appel invalide(s). Mandate Type is empty or invalid", "Title": "L'opération ne peut pas aboutir", "Priority": 2, "Date": "2026-01-19T15:23:20.4512095", "OperationId": "61cf74a45500d286dc787a61b1979b91", "ErrorDetails": null |
Error for a mandate activation
POST api/v2.0/accounts/accountId/mandates/mandateId/activate
| Use case | HTTP code | Code | Response |
|---|---|---|---|
| Wrong mandate status | 400 | 1025 | "Code": 1025, "ErrorMessage": "Only outgoing mandate in Created status can be activated.", "Title": "Invalid mandate status", "Priority": 2, "Date": "2026-01-19T15:21:51.8965169", "OperationId": "3f8ad554f25de193c11e395a90409298" |
| Signature in the future | 400 | 2 | "Code": 2, "ErrorMessage": "Signature date cannot be in the future", "Title": "Action not authorized", "Priority": 2, "Date": "2026-01-19T15:24:05.446649", "OperationId": "50545b3f8c333e4b58584d465f7c2b24" |
| Missing attribute | 400 | 715 | "Code": 715, "ErrorMessage": "Paramètre(s) d'appel invalide(s). 'Signature Date' must not be empty.", "Title": "L'opération ne peut pas aboutir", "Priority": 2, "Date": "2026-01-19T15:24:38.8877232", "OperationId": "543aee3040f2235e9aaf2c0e4c869ca8", "ErrorDetails": null |
Error for a SDD OUT creation
POST /api/v2.0/sepa-direct-debits
| Use case | SDD created ? | HTTP code | Code | Response |
|---|---|---|---|---|
| Incorrect executionDate | No | 400 | 715 | "Code": 715, "ErrorMessage": "Paramètre(s) d'appel invalide(s). expectedExecutionDate must be at least D+3.", "Title": "L'opération ne peut pas aboutir", "Priority": 2, "Date": "2026-01-20T08:57:03.8992613", "OperationId": "f89f6741f26c32624eb6a794200722ed", "ErrorDetails": null |
| Yes | 400 | 362 | "Code": 362, "ErrorMessage": "Opération non autorisée", "Title": "", "Priority": 2, "Date": "2026-01-20T08:57:38.4384898", "OperationId": "3ac7316c5d414a362986136b9609faa8" | |
| Missing or wrong attribute | No | 400 | 715 | "Code": 715, "ErrorMessage": "Paramètre(s) d'appel invalide(s). XXX is empty or invalid", "Title": "L'opération ne peut pas aboutir", "Priority": 2, "Date": "2026-01-20T08:58:40.9090588", "OperationId": "d145bcaf831e4c444d376bb209ac41a8", "ErrorDetails": null |
| Account does not exist | No | 400 | 147 | "Code": 147, "ErrorMessage": "Account does not exist", "Title": "The operation cannot succeed", "Priority": 2, "Date": "2026-01-20T08:58:57.998904", "OperationId": "ec6a66461e94d7b1c0bd381edb5a24c9" |
| Id already used | No | 400 | 710 | "Code": 710, "ErrorMessage": "Operation with sepaDirectDebitId already exists for the partner xxx.", "Title": "The operation cannot succeed", "Priority": 2, "Date": "2026-01-20T08:59:55.2351466", "OperationId": "72b22b68815cbb2aa464d3c010bbc003" |
| Mandate type mentionned is not the same than the one in the mandate | 400 | 2 | "Code": 2, "ErrorMessage": "SddType (Core) is not compatible with MandateType (B2B)", "Title": "Action not authorized", "Priority": 2, "Date": "2026-01-20T09:27:07.7111877", "OperationId": "67ed9b7fec9ffb97b790d82dbd1344bc" |
Error for a get sdd
GET /v2.0/sepa-direct-debits/sepaDirectDebitId
| Use case | HTTP code | Code | Response |
|---|---|---|---|
| Wrong request | 400 | 715 | "Code": 715, "ErrorMessage": "Paramètre(s) d'appel invalide(s). MandatePublicId must be a valid and non-empty GUID", "Title": "L'opération ne peut pas aboutir", "Priority": 2, "Date": "2026-01-20T09:00:49.6467942", "OperationId": "abe2e5f26f47169468a935a833c1a4d0", "ErrorDetails": null |
R-transactions
Some direct debit transactions require exception handling, because one of the parties involved does not or cannot process the collection in the
normal way. This exception handling involves the sending of messages called R-transactions because their names all start with an R: Refusals,
Rejects, Returns, Refunds, Reversals. The definitions of the various SDD R-transactions are outlined this document :
General scheme
sequenceDiagram Participant Before Participant D-14 Participant D-1 bank business day Participant D Payment Date Participant D5 bank business day Participant D8 weeks Participant D13 months Before -->> D-1 bank business day: Revocation by creditor D-14 -->> D Payment Date: Request for cancellation from creditor's bank D-14 -->> D Payment Date: Reject from the debitor's bank D-14 -->> D Payment Date: Refusal from the debitor's bank D Payment Date -->> D5 bank business day : Reversal by Creditor D Payment Date -->> D5 bank business day : Return D Payment Date -->> D8 weeks : Request for refund D8 weeks -->> D13 months : Request for refund for <br/>an unauthorized transaction
- Reject example: account closed
- Refusal by debtor example: the user debited by the SDD OUT refused
- Reversal by creditor example: external bank debit error.
- Return example: insufficient balance
General sequence diagram
In the case of a reject or a refusal the day or after the paymentDate, a new operation is created: this operation is named R-transaction.Each of these two operations has an independent status diagram, but the R-transaction is linked to the original operation through the field
refundReference.
Case refund after the payment date
sequenceDiagram
Title: R-transaction for a completed SDD OUT
autoNumber
Participant Partner
Participant XPO
Participant External_bank
Partner -->> XPO : SDD OUT
XPO -->> External_bank: SDD OUT
XPO -->> Partner: Webhook SepaDirectDebitCreatedOrUpdate {sepaDirectDebitId: X status 'Completed'}
Note over Partner, External_bank : Refund
External_bank -->> XPO: R-transaction refund
XPO -->> Partner: SepaDirectDebitCreatedOrUpdate {isRTransaction:true, status:'Completed', relatedSepaDirectDebitId:X}
The initial operation:
- has a status Completed
- has the refund reference in the attribute
relatedSepaDirectDebitId
The refund operation
isRTransaction- has a status Completed
- has the reference of the initial operation in the attribute
relatedSepaDirectDebitId
Case reject or refusal before the payment date
sequenceDiagram
Title: R-transaction for a rejected SDD OUT
autoNumber
Participant Partner
Participant XPO
Participant ESP
Note over Partner, ESP : X days before payment date
Partner -->> XPO : SDD OUT
XPO -->> ESP: SDD OUT
ESP -->> XPO: ok
XPO -->> Partner: Webhook SepaDirectDebitCreatedOrUpdate {sepaDirectDebitId:X, status 'Approved'}
Note over Partner, ESP : Rejected
ESP -->> XPO: Reject
XPO -->> Partner: SepaDirectDebitCreatedOrUpdate {sepaDirectDebitId:X, status 'Rejected'}
ESP = Sepa Exchanger
sepaRejectCode & sepaRejectReason
These attributes are visible in the webhook SepaDirectDebitCreatedOrUpdate.
They are filled when the SDD is refused and a R-transaction
Please referee to this link, page 5, to find all code, definition and associated use cases.
Updated 8 months ago