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

# How to send a SEPA transfer to a trusted beneficiary

Automating payments, such as supplier payouts, salary payments, or refunds to eliminate manual processing time and reduces the risk of human error. In this guide, we will list beneficiaries to find the right recipient, verify the payee identity through the Verification of Payee (VoP) service, and submit the transfer.

> **Example:** A freelance management platform automatically pays contractors every Friday based on approved timesheets, without anyone logging into Qonto manually.

**Prerequisites:**

* At least one beneficiary with `status: validated`.
* Scopes: `organization.read`, `payment.write`

> [!WARNING]
>
> Beneficiaries can be trusted via the API with the `beneficiary.trust` scope, available to applications using the **Automate your business operations** or [**Embed**](https://docs.qonto.com/partnerships/embed/overview.md) [use case](https://docs.qonto.com/guides/developer-portal/developer-guidelines.md#selecting-your-use-case). Otherwise, they must be trusted through the Qonto web app. Learn more about [sensitive scopes](https://docs.qonto.com/guides/developer-portal/developer-guidelines.md#sensitive-scopes).

### 1. List SEPA beneficiaries

Retrieve the list of validated beneficiaries and find the one you want to pay. You can filter by IBAN or name to narrow down the results.

Endpoint: [List SEPA beneficiaries](https://docs.qonto.com/api-reference/business-api/transfers/sepa-beneficiaries/index.md)

> [!NOTE]
>
> **OAuth scope required:** `organization.read`

**Python**

```python theme={null}
import requests

BASE_URL = "https://thirdparty.qonto.com/v2"
headers = {"Authorization": "Bearer {your_access_token}"}

response = requests.get(
    f"{BASE_URL}/sepa/beneficiaries",
    headers=headers,
    params={
        "iban[]": "FR7616798000010000005663951",  # Filter by IBAN
        "status[]": "validated",
        "per_page": 25,
    },
)
response.raise_for_status()

beneficiaries = response.json()["beneficiaries"]
beneficiary = beneficiaries[0]
beneficiary_id = beneficiary["id"]
beneficiary_name = beneficiary["name"]
print(f"Found beneficiary: {beneficiary['name']} ({beneficiary_id})")
```

**Node.js**

```javascript theme={null}
const BASE_URL = "https://thirdparty.qonto.com/v2";
const headers = { Authorization: "Bearer {your_access_token}" };

const params = new URLSearchParams();
params.append("iban[]", "FR7616798000010000005663951"); // Filter by IBAN
params.append("status[]", "validated");
params.append("per_page", 25);

const response = await fetch(`${BASE_URL}/sepa/beneficiaries?${params}`, { headers });
if (!response.ok) throw new Error(`HTTP ${response.status}`);

const { beneficiaries } = await response.json();
const beneficiary = beneficiaries[0];
const beneficiaryId = beneficiary.id;
const beneficiaryName = beneficiary.name;
console.log(`Found beneficiary: ${beneficiaryName} (${beneficiaryId})`);
```

### 2. Verify the SEPA payee (VoP)

Before creating a transfer, you **must** verify the payee through Verification of Payee (VoP). This returns a `proof_token` that you will include in the transfer request.

Endpoint: [Verify a SEPA payee](https://docs.qonto.com/api-reference/business-api/transfers/verification-of-payee/index.md)

> [!NOTE]
>
> **OAuth scope required:** `payment.write`

> [!WARNING]
>
> The `proof_token` is valid for **23 hours** only. Always verify immediately before creating the transfer. Excessive verifications not followed by a transfer may be rate-limited.

**Python**

```python theme={null}
response = requests.post(
    f"{BASE_URL}/sepa/verify_payee",
    headers={**headers, "Content-Type": "application/json"},
    json={
        "iban": "FR7616958000014849440866435",
        "beneficiary_name": beneficiary_name,
    },
)
response.raise_for_status()

data = response.json()
proof_token = data["proof_token"]["token"]
match_result = data["match_result"]

# match_result values:
# MATCH_RESULT_MATCH       → proceed with confidence
# MATCH_RESULT_CLOSE_MATCH → consider reviewing the name
# MATCH_RESULT_NO_MATCH    → caution, consider skipping transfer
# MATCH_RESULT_NOT_POSSIBLE → verification unavailable for this IBAN
print(f"Verification result: {match_result}")
```

**Node.js**

```javascript theme={null}
const verifyResponse = await fetch(`${BASE_URL}/sepa/verify_payee`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    iban: "FR7616958000014849440866435",
    beneficiary_name: beneficiaryName,
  }),
});
if (!verifyResponse.ok) throw new Error(`HTTP ${verifyResponse.status}`);

const response = await verifyResponse.json();
const proofToken = response.proof_token.token;
const matchResult = response.match_result;

// match_result values:
// MATCH_RESULT_MATCH       → proceed with confidence
// MATCH_RESULT_CLOSE_MATCH → consider reviewing the name
// MATCH_RESULT_NO_MATCH    → caution, consider skipping transfer
// MATCH_RESULT_NOT_POSSIBLE → verification unavailable for this IBAN
console.log(`Verification result: ${matchResult}`);
```

### 3. Create the SEPA transfer

Submit the transfer using the `beneficiary_id` from Step 1 and the `proof_token` from Step 2.

Endpoint: [Create a SEPA transfer](https://docs.qonto.com/api-reference/business-api/transfers/sepa-transfers/create.md)

> [!NOTE]
>
> **OAuth scope required:** `payment.write`

> [!NOTE]
>
> Do not forget to include the `X-Qonto-Idempotency-Key` header to prevent duplicate transfers in case of network errors. See [Idempotent requests](https://docs.qonto.com/api-reference/business-api/introduction/idempotency.md).

> [!NOTE]
>
> To retrieve your `bank_account_id`, needed in this request, call [`GET /v2/organization`](https://docs.qonto.com/api-reference/business-api/organization-accounts/organizations/retrieve-the-authenticated-organization-and-list-bank-accounts) or [`GET /v2/banks_accounts`](https://docs.qonto.com/api-reference/business-api/organization-accounts/business-accounts/list), the responses include a `bank_accounts` array, each with an `id` field.

> [!WARNING]
>
> Transfers above **€30,000** require at least one attachment. Upload the attachment first via [`POST /v2/attachments`](https://docs.qonto.com/api-reference/business-api/transactions-statements/attachments/upload-an-attachment) and include its ID in the request.

**Python**

```python {11, 16} theme={null}
import uuid

response = requests.post(
    f"{BASE_URL}/sepa/transfers",
    headers={
        **headers,
        "Content-Type": "application/json",
        "X-Qonto-Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "vop_proof_token": proof_token,
        "transfer": {
            "bank_account_id": "{your_bank_account_id}",
            "reference": "Invoice payment INV-001",
            "amount": "1100.50",
            "beneficiary_id": beneficiary_id,
            # "scheduled_date": "2026-04-01",  # Optional: ISO 8601 date
            # "attachment_ids": ["uuid-1"],     # Required if amount > €30,000
        },
    },
)
response.raise_for_status()

transfer = response.json()["transfer"]
print(f"Transfer created: {transfer['id']} — status: {transfer['status']}")
```

**Node.js**

```javascript {11, 16} theme={null}
const { randomUUID } = await import("node:crypto");

const transferResponse = await fetch(`${BASE_URL}/sepa/transfers`, {
  method: "POST",
  headers: {
    ...headers,
    "Content-Type": "application/json",
    "X-Qonto-Idempotency-Key": randomUUID(),
  },
  body: JSON.stringify({
    vop_proof_token: proofToken,
    transfer: {
      bank_account_id: "{your_bank_account_id}",
      reference: "Invoice payment INV-001",
      amount: "1100.50",
      beneficiary_id: beneficiaryId,
      // scheduled_date: "2026-04-01",  // Optional: ISO 8601 date
      // attachment_ids: ["uuid-1"],     // Required if amount > €30,000
    },
  }),
});
if (!transferResponse.ok) throw new Error(`HTTP ${transferResponse.status}`);

const { transfer } = await transferResponse.json();
console.log(`Transfer created: ${transfer.id} — status: ${transfer.status}`);
```

> [!TIP]
>
> **Instant transfer limits:** Instant transfers fall back to standard SEPA if the amount exceeds the limit. For trusted beneficiaries: €10,000 per transfer or €50,000 within 24h.

**Example output:**

```
[Step 1] GET /sepa/beneficiaries
  Found beneficiary: Admin (0199cd7a-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

[Step 2] POST /sepa/verify_payee
  Verification result: MATCH_RESULT_MATCH
  proof_token: 1|1|1773938795|MEUCI… (valid 23h)

[Step 3] POST /sepa/transfers
  Transfer created: 019d06fd-xxxx-xxxx-xxxx-xxxxxxxxxxxx — status: pending
```

> [!TIP]
>
> We now have a submitted SEPA transfer. The transfer `id` and `status` in the response confirm it has been accepted for processing.

***
