> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qonto.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Collect payments with SEPA Direct Debit

> Collect payments with SEPA Direct Debit from your customers

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.

<Note>To use the API, you must be eligible for SEPA Direct Debit and have the feature activated in the Qonto app. Go to Business Account → Incoming Direct Debits to check your eligibility and create your SCI (SEPA Creditor Identifier).</Note>

<Info>To test the API in the sandbox environment, follow the [sandbox setup guide](/get-started/business-api/use-cases/enable-sdd-collections) to enable SDD collections for your test organization.</Info>

***

## 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:

| Scope | Access |
| - | - |
| `sepa_direct_debit.read` | Read mandates, subscriptions, and collections |
| `sepa_direct_debit.write` | Create and cancel mandates, create subscriptions |

You can manage your OAuth credentials from the [Developer Portal](https://developers.qonto.com).

***

### 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 first-payment details on the mandate for the signature request and approval communications. It does not create or schedule a collection.

Minimal request (mandate only):

```json theme={null}
{
  "direct_debit_mandate": {
    "client_id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  }
}
```

You can omit `payment_info` to create only the mandate. Include it to attach first-payment details to the mandate; it does not create a collection. To collect after the customer signs, create a subscription via `POST /v2/sepa/direct_debit_subscriptions` referencing the mandate and payment details.

Example with `payment_info`:

```json theme={null}
{
  "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
  }
}
```

When the mandate is awaiting signature, the response includes a `sign_url` — a link your customer must visit to sign the mandate electronically, whether or not `payment_info` was provided. You can send this URL yourself or have Qonto send the signature request email automatically by setting `send_mandate_signature_email: true`. The email can be sent for a standalone mandate; it omits the amount and date when `payment_info` is absent.

```json theme={null}
{
  "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`.

When a client IBAN is associated with the mandate, list and retrieve responses also include `iban` with the last four digits visible (for example, `••••3000`).

Once your customer signs, you will receive a `v1/sepa-direct-debit-mandates` webhook with event `accepted` (see [Webhooks](#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`:

```json theme={null}
{
  "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](#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}`.

```json theme={null}
{
  "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

| Status | Description |
| - | - |
| `pending_signature` | The mandate has been created but not yet signed by the customer |
| `approved` | The mandate has been signed and is ready to use for collections |
| `canceled` | The mandate has been cancelled. |

***

## Collection statuses

| Status | Description |
| - | - |
| `pending` | The collection has been scheduled and is awaiting processing |
| `completed` | The payment was successfully collected and settled |
| `declined` | The collection was declined before processing |
| `rejected` | The collection was rejected during processing |
| `canceled` | The collection was canceled |
| `returned` | The payment was reversed by the debtor's bank (typically up to D+5 after settlement) |
| `refunded` | The 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`

| Event | Description |
| - | - |
| `accepted` | The mandate has been signed by the customer |

Example payload:

```json theme={null}
{
  "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`

| Event | Description |
| - | - |
| `completed` | The payment was successfully collected and settled |
| `failed` | The collection did not succeed. Check `data.status` for the fine-grained reason (`declined`, `rejected`, or `canceled`) and `data.status_reason` for more details |
| `returned` | The payment was reversed by the debtor's bank, typically within D+5 of settlement |
| `refunded` | The 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):

```json theme={null}
{
  "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}`

| Step | Endpoint |
| - | - |
| Create a mandate | `POST /v2/sepa/direct_debit_mandates` |
| Get a mandate | `GET /v2/sepa/direct_debit_mandates/{id}` |
| List mandates | `GET /v2/sepa/direct_debit_mandates?client_id={id}` |
| Cancel a mandate | `POST /v2/sepa/direct_debit_mandates/{id}/cancel` |
| Create a subscription | `POST /v2/sepa/direct_debit_subscriptions` |
| Get a subscription | `GET /v2/sepa/direct_debit_subscriptions/{id}` |
| List subscriptions | `GET /v2/sepa/direct_debit_subscriptions` |
| Get a collection outcome | `GET /v2/sepa/direct_debit_collections/{id}` |
| List collection outcomes | `GET /v2/sepa/direct_debit_collections` |
