Skip to main content
SEPA Direct Debit (SDD) lets you collect payments directly from your customers’ bank accounts — no manual action required in the Qonto app. With the SDD Collection API, you can automate your entire receivables workflow: create mandates, trigger one-off collections, and track outcomes in real time. This is particularly useful if you:
  • Issue invoices from an external tool (e.g. an ERP or invoicing platform) and want to trigger SDD collections programmatically
  • Build a direct debit payment method into your own product on top of Qonto
This guide walks you through the available API endpoints and how to integrate them into your business operations.
SEPA Direct Debit must be activated in the Qonto app before using this API. Your organization must also have a valid ICS (SEPA Creditor Identifier).

How SDD collection works

1. Authenticate with the right scopes

All SDD endpoints are protected by OAuth 2.0. Request the following scopes depending on the operations you need:
ScopeAccess
sepa_direct_debit.readRead mandates, subscriptions, and collections
sepa_direct_debit.writeCreate mandates and subscriptions
You can manage your OAuth credentials from the Developer Portal.

2. Create a mandate

A mandate is the authorization from your customer (the debtor) to collect payments from their bank account. You must have a valid, signed mandate before collecting any payment. To create a mandate, send a POST request to /v2/sepa/direct_debit_mandates. The payment_info object is optional; when provided, it stores the first payment details on the mandate and is used for the signature request and for the approval flow (e.g. for creating or scheduling the first collection once the mandate is signed). Minimal request (mandate only):
{
  "direct_debit_mandate": {
    "client_id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  }
}
You can omit payment_info to create only the mandate. To attach first payment details and use them for the signature request and approval flow, include the optional payment_info object. To have a collection run after the customer signs, create a subscription via POST /v2/sepa/direct_debit_subscriptions referencing the mandate and the same payment details. Example with payment_info:
{
  "direct_debit_mandate": {
    "client_id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "payment_info": {
      "first_payment": {
        "collection_date": "2026-01-01",
        "amount": { "value": "250.00", "currency": "EUR" },
        "reference": "INV-2025-001"
      },
      "notify_client": true,
      "schedule_type": "one_off"
    },
    "send_mandate_signature_email": true
  }
}
The response includes a sign_url — a link your customer must visit to sign the mandate electronically. You can send this URL yourself or have Qonto send the signature request email automatically by setting send_mandate_signature_email: true.
{
  "direct_debit_mandate": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "unique_mandate_reference": "UMR-...",
    "client_id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "status": "pending_signature",
    "schedule_type": "one_off",
    "notify_client": true,
    "sign_url": "https://...",
    "created_at": "2026-01-01T10:00:00Z"
  }
}
When payment_info was included in the request, the response includes schedule_type and notify_client. Once your customer signs, you will receive a v1/sepa-direct-debit-mandates webhook with event accepted (see Webhooks below). You can also poll the mandate status with a GET request to /v2/sepa/direct_debit_mandates/{direct_debit_mandate_id}. You can list all mandates for a given client by sending a GET request to /v2/sepa/direct_debit_mandates?client_id={client_id}.

3. Create a subscription

A subscription represents a one-off payment request against a mandate. Once you have a signed mandate, you can trigger a subscription at any time. Send a POST request to /v2/sepa/direct_debit_subscriptions:
{
  "direct_debit_subscription": {
    "client_id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "direct_debit_mandate_id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "bank_account_id": "497f6eca-6276-4993-bfeb-53cbbbba6f09",
    "initial_collection_date": "2026-01-01",
    "amount": { "value": "250.00", "currency": "EUR" },
    "reference": "INV-2025-001",
    "notify_client": true,
    "schedule_type": "one_off"
  }
}
Using an existing mandate: provide the direct_debit_mandate_id as shown above. Creating a mandate and collection in one step: omit direct_debit_mandate_id. A new mandate will be created automatically and the response will include a sign_url. You can retrieve a specific subscription with a GET request to /v2/sepa/direct_debit_subscriptions/{direct_debit_subscription_id}, or list all subscriptions with GET /v2/sepa/direct_debit_subscriptions.

4. Track collection outcomes

Once a subscription has been triggered, Qonto processes it through the SEPA banking network. You can track the outcome in two ways: Webhooks (recommended): subscribe to v1/sepa-direct-debit-collections to receive real-time notifications when a collection status changes (see Webhooks below). Polling: retrieve a collection by ID with a GET request to /v2/sepa/direct_debit_collections/{direct_debit_collection_id}, or list all collections — optionally filtered by subscription — with GET /v2/sepa/direct_debit_collections?direct_debit_subscription_id={id}.
{
  "direct_debit_collection": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "direct_debit_subscription_id": "497f6eca-6276-4993-bfeb-53cbbbba6f09",
    "amount": { "value": "250.00", "currency": "EUR" },
    "collection_date": "2026-01-01",
    "status": "completed",
    "unique_mandate_reference": "UMR-..."
  }
}

Mandate statuses

StatusDescription
pending_signatureThe mandate has been created but not yet signed by the customer
approvedThe mandate has been signed and is ready to use for collections

Collection statuses

StatusDescription
pendingThe collection has been scheduled and is awaiting processing
completedThe payment was successfully collected and settled
declinedThe collection was declined before processing
rejectedThe collection was rejected during processing
canceledThe collection was canceled
returnedThe payment was reversed by the debtor’s bank (typically up to D+5 after settlement)
refundedThe payment was reversed following a request by the debtor (typically up to 8 weeks after settlement)
When a collection fails, the status_reason field provides additional detail (e.g. insufficient_funds, amount_limit_reached, account_closed). The full list of allowed values is documented in the API reference.

Webhooks

Subscribe to webhook topics to receive real-time notifications about key events. The event field in the webhook payload body identifies what happened.

v1/sepa-direct-debit-mandates

EventDescription
acceptedThe mandate has been signed by the customer
Example payload:
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "organization_id": "123e4567-e89b-12d3-a456-426614174000",
  "type": "v1/sepa-direct-debit-mandates",
  "created_at": "2026-01-01T10:55:00Z",
  "data": {
    "event": "accepted",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "unique_mandate_reference": "UMR-...",
    "status": "approved",
    "mandate_signature_date": "2026-01-01T10:54:00Z"
  }
}

v1/sepa-direct-debit-collections

EventDescription
completedThe payment was successfully collected and settled
failedThe collection did not succeed. Check data.status for the fine-grained reason (declined, rejected, or canceled) and data.status_reason for more details
returnedThe payment was reversed by the debtor’s bank, typically within D+5 of settlement
refundedThe payment was reversed at the debtor’s request, typically up to 8 weeks after settlement
Tip: The event field uses a simplified set of outcomes (completed, failed, returned, refunded). For failed events, data.status retains the fine-grained value (declined, rejected, or canceled) so you can handle each case precisely.
Example payload (failed):
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "organization_id": "123e4567-e89b-12d3-a456-426614174000",
  "type": "v1/sepa-direct-debit-collections",
  "created_at": "2026-01-01T10:55:00Z",
  "data": {
    "event": "failed",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "direct_debit_subscription_id": "497f6eca-6276-4993-bfeb-53cbbbba6f09",
    "amount": { "value": "250.00", "currency": "EUR" },
    "reference": "INV-2025-001",
    "status": "rejected",
    "status_reason": "insufficient_funds"
  }
}

Summary

Here are the steps to follow when integrating SDD collection:
  1. Request the right OAuth scopes: sepa_direct_debit.read and/or sepa_direct_debit.write from the Developer Portal
  2. Create a mandate: POST /v2/sepa/direct_debit_mandates — share or send the sign_url to your customer
  3. Wait for mandate acceptance: subscribe to v1/sepa-direct-debit-mandates webhooks, or poll GET /v2/sepa/direct_debit_mandates/{id}
  4. Create a subscription: POST /v2/sepa/direct_debit_subscriptions with the signed mandate ID, amount, and collection date
  5. Track the outcome: subscribe to v1/sepa-direct-debit-collections webhooks, or poll GET /v2/sepa/direct_debit_collections/{id}
StepEndpoint
Create a mandatePOST /v2/sepa/direct_debit_mandates
Get a mandateGET /v2/sepa/direct_debit_mandates/{id}
List mandatesGET /v2/sepa/direct_debit_mandates?client_id={id}
Create a subscriptionPOST /v2/sepa/direct_debit_subscriptions
Get a subscriptionGET /v2/sepa/direct_debit_subscriptions/{id}
List subscriptionsGET /v2/sepa/direct_debit_subscriptions
Get a collection outcomeGET /v2/sepa/direct_debit_collections/{id}
List collection outcomesGET /v2/sepa/direct_debit_collections