The Wallet Payout API pays out a customer’s wallet balance to a bank account. Fynn debits the balance immediately and generates a SEPA credit transfer. How the transfer reaches your bank depends on the configured submission mode: in manual mode (default) you download the generated SEPA file and submit it to your bank yourself, then confirm the upload so the payout moves to submitted; in automatic mode Fynn submits it over EBICS. The payout is only finalized once the bank confirms the transfer via the account statement.
Bank payouts are subject to origin-based routing rules. A wallet balance can only be paid out to a bank account if it originated from a bank transfer or an in-house SEPA direct debit. Balance funded by card, PayPal, or GoCardless must be refunded through the original channel. See Origin routing below.
Create a Payout
curl -X POST https://coreapi.io/api/customers/CUSTOMER_ID/wallet/payouts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"amount": 5000,
"currencyCode": "EUR",
"reference": "Wallet payout March 2026"
}'
Response (201 Created):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "created",
"amount": 5000,
"currencyCode": "EUR",
"endingBalance": 0,
"recipientIban": "DE89 **** **** **** **89",
"endToEndId": "WP2026030812345678",
"createdAt": "2026-03-08T10:00:00Z"
}
Request Fields
| Field | Type | Required | Description |
|---|
amount | integer | Yes | Payout amount in the smallest currency unit (cents). Must be greater than 0 |
currencyCode | string | Yes | ISO 4217 currency code (e.g. EUR) |
iban | string | No | Recipient IBAN. Defaults to the customer’s stored bank connection (SEPA mandate) |
bic | string | No | Recipient BIC, when an explicit iban is provided |
accountHolder | string | No | Recipient account holder name. Defaults to the customer’s display name |
reference | string | No | Remittance reference shown on the bank statement (max 140 characters) |
description | string | No | Internal description of the payout (max 140 characters) |
Amounts are integers in cents, not decimals. 5000 means 50,00 EUR.
Response Fields
| Field | Type | Description |
|---|
id | string | Payout UUID |
status | string | Payout status (created on success) |
amount | integer | Payout amount in cents |
currencyCode | string | ISO 4217 currency code |
endingBalance | integer | Remaining wallet balance in cents after the payout was booked |
recipientIban | string | Masked recipient IBAN |
endToEndId | string | Unique end-to-end reference used to match the bank statement entry |
createdAt | string | ISO 8601 timestamp |
Without an iban, the payout uses the customer’s stored bank connection (the active SEPA mandate’s bank account). Pass an explicit iban to pay out to a different account; it is recorded on the payout for audit.
Payout Status
A payout moves through a fixed lifecycle:
| Status | Description |
|---|
created | Payout booked, wallet balance debited. The credit transfer is waiting to be submitted: in manual mode until you download the SEPA file and confirm the upload, in automatic mode until Fynn submits it over EBICS |
submitted | The credit transfer was submitted to the bank, either after you confirmed the upload (manual mode) or over EBICS (automatic mode) |
executed | The bank executed the transfer, confirmed via the account statement. Terminal state |
failed | Submission failed. The wallet booking was automatically reversed and the balance restored. Terminal state |
created does not mean the money has left the bank account yet. The payout is only complete once it reaches executed. Subscribe to the webhooks to react to the terminal states.
Origin Routing
Fynn records the origin of every wallet inflow and enforces where the balance may flow back. A bank payout is only allowed when every funding portion of the payout comes from an allowed origin.
| Origin of the balance | Bank payout | Correct alternative |
|---|
| Bank transfer | Allowed | Payout via SEPA credit transfer |
| SEPA direct debit (in-house) | Allowed | Payout via SEPA credit transfer |
| Card (Stripe, Unzer) | Blocked | Refund via the original card |
| PayPal | Blocked | Refund via PayPal |
| GoCardless | Blocked | Refund via GoCardless |
| Missing / unknown origin | Blocked | Manual review, then original channel |
A blocked payout is not booked. The request returns 422 with an error code identifying the reason. Mixed funding follows an all-or-nothing rule: a single blocked portion blocks the entire payout.
Error Handling
| Status Code | Error Code | Scenario |
|---|
422 | CUSTOMER_BALANCE__NEGATIVE_NOT_ALLOWED | Insufficient wallet balance for the requested amount |
422 | WALLET_PAYOUT__ROUTE_NOT_ALLOWED | Balance origin does not permit a bank payout (e.g. card-funded) |
422 | WALLET_PAYOUT__ROUTE_UNKNOWN_ORIGIN | Origin of the balance is unknown and requires manual review |
422 | WALLET_PAYOUT__MISSING_BANK_DATA | No recipient bank connection available and no iban provided |
422 | WALLET_PAYOUT__NOT_CONFIGURED | Required configuration is missing. In manual mode this means the SEPA credit transfer settings (sender bank account); in automatic mode it additionally requires the EBICS connection |
404 | (none) | Unknown customer |
When a payout is blocked or rejected, nothing is booked. The wallet balance stays exactly as it was before the request.
Webhooks
Subscribe to these events to react to the terminal states of a payout. Both carry the same payload shape.
| Event | When |
|---|
wallet.payout.executed | The bank executed the transfer and it was confirmed via the account statement |
wallet.payout.failed | Submission failed; the wallet balance was automatically restored |
Payload:
{
"payoutId": "550e8400-e29b-41d4-a716-446655440000",
"customerId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"amount": 5000,
"currencyCode": "EUR",
"status": "executed",
"endToEndId": "WP2026030812345678",
"reference": "Wallet payout March 2026",
"failReason": null,
"executedAt": "2026-03-10T08:15:00Z",
"failedAt": null
}
| Field | Type | Description |
|---|
payoutId | string | Payout UUID |
customerId | string | Customer UUID |
amount | integer | Payout amount in cents |
currencyCode | string | ISO 4217 currency code |
status | string | executed or failed |
endToEndId | string | End-to-end reference matching the bank statement entry |
reference | string | Remittance reference of the payout |
failReason | string | null | Reason for failure; null for executed payouts |
executedAt | string | null | ISO 8601 timestamp when executed; null for failed payouts |
failedAt | string | null | ISO 8601 timestamp when failed; null for executed payouts |
See Webhooks for signature verification and setup.