Skip to main content
BVNK

Send fiat payouts

Beta

Payments v.3 API endpoints are in beta and may change as the product evolves. For foundational concepts, see Payments API v.3.

Local banking network fields are not defined yet

The v.3 specification does not yet define the required bank details for each local banking network. Contact your Account Manager before you send payouts in a local currency.

Fiat and stablecoin payouts use the same endpoint, POST /payment/v3/payouts, and share the quote and status engine. A fiat payout follows the same process as a stablecoin payout. Do not include a payment method in your request. BVNK infers it from beneficiary.paymentInstrument.type, which is BANK_ADDRESS for a bank account, and returns method: "FIAT" in responses and webhooks.

You can fund a fiat payout from any of your wallets, whether fiat or crypto. If the wallet currency differs from the payout currency, BVNK converts the funds during the payout. For example, a USDC wallet can pay a supplier in EUR. The wallet currency serves as the originator currency for the payout:

Wallet typeCurrenciesConversion
FiatUSD, EUR, GBPNone when the wallet and payout currencies match, for example a EUR wallet paying out EUR. Otherwise, BVNK converts the funds.
CryptoStablecoins such as USDC, USDT, and EURC, and other supported cryptocurrenciesAlways. BVNK converts from the wallet currency into the payout currency.

BVNK pays out USD, EUR, and GBP via local and international payment networks, and supports eight additional currencies through local banking networks. Local banking networks process payments domestically in the beneficiary's country, without using SWIFT or virtual accounts. To pay out in one of these currencies, set beneficiary.currency accordingly, for example, CAD.

For details on payment networks, delivery times, and cut-off times by currency, see Fiat payout networks.

Prerequisites​

To send a fiat payout, ensure you have the following:

  • Your wallet ID: the fiat or crypto wallet to debit, sent as originator.walletId. BVNK derives originator.currency from the wallet.
  • The beneficiary: your payee's full name, or legal name for a company, and address, sent as beneficiary.entity. Alternatively, reference a stored contact with beneficiary.contactId. See Manage contacts.
  • The beneficiary's bank details: sent as beneficiary.paymentInstrument with "type": "BANK_ADDRESS". Set accountNumberFormat to match accountNumber. What you need depends on the currency and the payment network:
    • EUR: IBAN (IBAN) and the bank's BIC in bank.bic.
    • GBP: IBAN (IBAN), or UK account number and sort code (SCAN), with the sort code in bank.nid.
    • USD: account number (ABA), the ABA routing number in bank.nid, and accountType.
    • Local currencies: account number, bank details. The specific required fields depend on the currency.
    • SWIFT: account number in any format, the bank's BIC, the bank's name and address in bank.address, and the payee's full name and address. If the payout routes through correspondent banks, list them in intermediaryBanks[].

EUR payouts require the least information. For USD and SWIFT payouts, provide complete beneficiary and bank details to minimise the risk of rejection. Always include the beneficiary's full address, even though v.3 requires only country. US local networks also require postCode and region, and SWIFT requires postCode.

SWIFT payouts use the SHA (shared) fee model. Intermediary and beneficiary banks may deduct their own fees so that the payee may receive less than the amount sent. Contact your Account Manager for SWIFT fee details.

Create a payout​

You can send a fiat payout using one of two methods:

  • Request a quote to fix either the amount debited from your wallet or the amount the payee receives. Adjust as needed, then accept the quote to send the payout. This approach provides your customer with a firm price before funds are moved. See With a quote.
  • Send the payout with all required details in a single call. BVNK automatically assigns the exchange rate and processes the payout immediately. See Without a quote.

Both methods are available for all supported payout currencies, including the eight currencies BVNK pays out through local banking networks, such as CAD and BRL. See Supported wallets and currencies.

Both methods use the same POST /payment/v3/payouts endpoint. BVNK determines whether to hold the payout as a quote or send it immediately based on the presence of beneficiary bank details in the request.

Request a quote to provide your customer with a firm price before funds are moved. Fix either the debit or credit amount, and BVNK will calculate the other based on the current rate, updating it with each reprice:

  • Fixed debit: set originator.amount to spend exactly this much from your wallet. What your payee receives moves with the rate.
  • Fixed credit: set beneficiary.amount so your payee receives exactly this much. What leaves your wallet moves with the rate.

For fiat payouts, include either beneficiary.entity or beneficiary.contactId when creating the quote. BVNK cannot price fees without a beneficiary, so quotes without one will not return fee information. Providing the beneficiary details upfront also completes compliance screening before presenting a price to your customer.

Withhold bank details until your customer is ready to proceed. The quote remains at PENDING_QUOTE_ACCEPTANCE until it is accepted.

Bank details on the create call send the payout

Omitting bank details keeps the payout as a quote. If you include bank details when creating the payout, BVNK accepts the quote for you at the current rate and sends the payout immediately, as described in the Without a quote section.

The examples below pay John Doe, a contractor in Germany, in EUR from a USD wallet. To pay out in a local banking network currency instead, set beneficiary.currency to it, for example CAD. The steps are the same.

  1. Create the quote by sending the POST /payment/v3/payouts request with originator.amount, beneficiary.currency, and the beneficiary, but no bank details:

    Request: POST /payment/v3/payouts (fixed debit quote)
    {
    "reference": "REF-FIAT-4418",
    "originator": {
    "amount": "1000.00",
    "walletId": "a:24072237783989:Unkx9kW:1"
    },
    "beneficiary": {
    "currency": "EUR",
    "requesterIpAddress": "172.16.254.1",
    "entity": {
    "type": "INDIVIDUAL",
    "firstName": "John",
    "lastName": "Doe",
    "dateOfBirth": "1984-06-30",
    "relationshipType": "THIRD_PARTY",
    "address": {
    "addressLine1": "Hauptstrasse 42",
    "addressLine2": null,
    "city": "Munich",
    "region": "Bavaria",
    "postCode": "80331",
    "country": "DE"
    }
    }
    }
    }

    BVNK prices the payout and holds it as a quote:

    Response: POST /payment/v3/payouts (fixed debit quote)
    {
    "id": "7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17",
    "reference": "REF-FIAT-4418",
    "type": "payment:payout",
    "status": "PENDING_QUOTE_ACCEPTANCE",
    "direction": "OUT",
    "method": "FIAT",
    "fees": {
    "customerFee": null,
    "processingFee": { "estimated": { "currency": "USD", "amount": "1.00" }, "actual": { "currency": "USD", "amount": "0.00" } }
    },
    "originator": {
    "required": { "currency": "USD", "amount": "1000.00" },
    "actual": { "currency": "USD", "amount": "0.00" },
    "walletId": "a:24072237783989:Unkx9kW:1"
    },
    "beneficiary": {
    "required": { "currency": "EUR", "amount": "857.76" },
    "actual": { "currency": "EUR", "amount": "0.00" },
    "customerId": null,
    "customerReference": null,
    "requesterIpAddress": "172.16.254.1",
    "entity": {
    "type": "INDIVIDUAL",
    "firstName": "John",
    "lastName": "Doe",
    "dateOfBirth": "1984-06-30",
    "relationshipType": "THIRD_PARTY",
    "address": {
    "addressLine1": "Hauptstrasse 42",
    "addressLine2": null,
    "city": "Munich",
    "region": "Bavaria",
    "postCode": "80331",
    "country": "DE"
    }
    }
    },
    "conversion": {
    "type": "QUOTE",
    "baseRate": "0.862070",
    "allInRate": "0.857759",
    "spread": { "percentage": "0.005", "amount": "5.00", "currency": "USD" },
    "digest": "3f9a6c1e84b2d057",
    "validityDuration": "PT1H",
    "expiresAt": "2026-10-14T10:15:00Z",
    "priceLockDuration": "PT30S",
    "priceLockExpiresAt": "2026-10-14T09:15:30Z"
    },
    "instructions": [],
    "trackingDetails": [],
    "labels": [],
    "relatedPayments": [],
    "statusHistory": [
    { "status": "PENDING_QUOTE_ACCEPTANCE", "timestamp": "2026-10-14T09:15:00Z" }
    ],
    "flow": "default",
    "metadata": {},
    "expiryDuration": "PT1H",
    "expiresAt": "2026-10-14T10:15:00Z",
    "updatedAt": "2026-10-14T09:15:00Z",
    "createdAt": "2026-10-14T09:15:00Z"
    }

    conversion.type is QUOTE, and originator.required.amount is the amount you fixed. BVNK calculated beneficiary.required.amount from conversion.allInRate. Because the beneficiary is already known, fees.processingFee is firm from this first response. fees.networkFee is omitted: network fees apply to on-chain payouts only.

  2. If the quote is about to expire and neither the amount nor the beneficiary needs to change, refresh it by sending the POST /payment/v3/payouts/{id}/action request with "type": "REFRESH_QUOTE". Include the latest conversion.digest so BVNK reprices the quote your customer last saw:

    Request: POST /payment/v3/payouts/7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17/action
    {
    "type": "REFRESH_QUOTE",
    "digest": "3f9a6c1e84b2d057"
    }

    The payout stays at PENDING_QUOTE_ACCEPTANCE with a new rate and a new digest. originator.required.amount stays fixed, and beneficiary.required.amount moves with the rate:

    Response: POST /payment/v3/payouts/7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17/action (REFRESH_QUOTE)
    {
    "id": "7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17",
    "reference": "REF-FIAT-4418",
    "type": "payment:payout",
    "status": "PENDING_QUOTE_ACCEPTANCE",
    "direction": "OUT",
    "method": "FIAT",
    "fees": {
    "customerFee": null,
    "processingFee": { "estimated": { "currency": "USD", "amount": "1.00" }, "actual": { "currency": "USD", "amount": "0.00" } }
    },
    "originator": {
    "required": { "currency": "USD", "amount": "1000.00" },
    "actual": { "currency": "USD", "amount": "0.00" },
    "walletId": "a:24072237783989:Unkx9kW:1"
    },
    "beneficiary": {
    "required": { "currency": "EUR", "amount": "857.23" },
    "actual": { "currency": "EUR", "amount": "0.00" },
    "customerId": null,
    "customerReference": null,
    "requesterIpAddress": "172.16.254.1",
    "entity": {
    "type": "INDIVIDUAL",
    "firstName": "John",
    "lastName": "Doe",
    "dateOfBirth": "1984-06-30",
    "relationshipType": "THIRD_PARTY",
    "address": {
    "addressLine1": "Hauptstrasse 42",
    "addressLine2": null,
    "city": "Munich",
    "region": "Bavaria",
    "postCode": "80331",
    "country": "DE"
    }
    }
    },
    "conversion": {
    "type": "QUOTE",
    "baseRate": "0.861540",
    "allInRate": "0.857232",
    "spread": { "percentage": "0.005", "amount": "5.00", "currency": "USD" },
    "digest": "b86d02f4a1c93e75",
    "validityDuration": "PT59M18S",
    "expiresAt": "2026-10-14T10:15:00Z",
    "priceLockDuration": "PT30S",
    "priceLockExpiresAt": "2026-10-14T09:16:12Z"
    },
    "instructions": [],
    "trackingDetails": [],
    "labels": [],
    "relatedPayments": [],
    "statusHistory": [
    { "status": "PENDING_QUOTE_ACCEPTANCE", "timestamp": "2026-10-14T09:15:00Z" }
    ],
    "flow": "default",
    "metadata": {},
    "expiryDuration": "PT1H",
    "expiresAt": "2026-10-14T10:15:00Z",
    "updatedAt": "2026-10-14T09:15:42Z",
    "createdAt": "2026-10-14T09:15:00Z"
    }
    conversion.digest

    digest is a fingerprint of the current quote. BVNK issues a new one on create, on every REFRESH_QUOTE, and on every PATCH, because a PATCH reprices the whole quote whether or not you change an amount. REFRESH_QUOTE requires the latest digest and rejects a stale one, so a reprice always acts on the quote your customer last saw. ACCEPT_QUOTE doesn't need a digest and doesn't issue a new one.

  3. If your customer wants a different amount, send the PATCH /payment/v3/payouts/{id} request with the same field you fixed. A PATCH reprices the whole quote.

    To switch to a fixed credit instead, set beneficiary.amount:

    Request: PATCH /payment/v3/payouts/7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17
    {
    "originator": {
    "amount": "1200.00"
    }
    }
    Response: PATCH /payment/v3/payouts/7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17 (new amount)
    {
    "id": "7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17",
    "reference": "REF-FIAT-4418",
    "type": "payment:payout",
    "status": "PENDING_QUOTE_ACCEPTANCE",
    "direction": "OUT",
    "method": "FIAT",
    "fees": {
    "customerFee": null,
    "processingFee": { "estimated": { "currency": "USD", "amount": "1.00" }, "actual": { "currency": "USD", "amount": "0.00" } }
    },
    "originator": {
    "required": { "currency": "USD", "amount": "1200.00" },
    "actual": { "currency": "USD", "amount": "0.00" },
    "walletId": "a:24072237783989:Unkx9kW:1"
    },
    "beneficiary": {
    "required": { "currency": "EUR", "amount": "1028.68" },
    "actual": { "currency": "EUR", "amount": "0.00" },
    "customerId": null,
    "customerReference": null,
    "requesterIpAddress": "172.16.254.1",
    "entity": {
    "type": "INDIVIDUAL",
    "firstName": "John",
    "lastName": "Doe",
    "dateOfBirth": "1984-06-30",
    "relationshipType": "THIRD_PARTY",
    "address": {
    "addressLine1": "Hauptstrasse 42",
    "addressLine2": null,
    "city": "Munich",
    "region": "Bavaria",
    "postCode": "80331",
    "country": "DE"
    }
    }
    },
    "conversion": {
    "type": "QUOTE",
    "baseRate": "0.861540",
    "allInRate": "0.857232",
    "spread": { "percentage": "0.005", "amount": "6.00", "currency": "USD" },
    "digest": "d4e1a97c36f0b258",
    "validityDuration": "PT58M25S",
    "expiresAt": "2026-10-14T10:15:00Z",
    "priceLockDuration": "PT30S",
    "priceLockExpiresAt": "2026-10-14T09:17:05Z"
    },
    "instructions": [],
    "trackingDetails": [],
    "labels": [],
    "relatedPayments": [],
    "statusHistory": [
    { "status": "PENDING_QUOTE_ACCEPTANCE", "timestamp": "2026-10-14T09:15:00Z" }
    ],
    "flow": "default",
    "metadata": {},
    "expiryDuration": "PT1H",
    "expiresAt": "2026-10-14T10:15:00Z",
    "updatedAt": "2026-10-14T09:16:35Z",
    "createdAt": "2026-10-14T09:15:00Z"
    }
  4. Add the beneficiary's bank details by sending the PATCH /payment/v3/payouts/{id} request while the payout is still a quote. When you update a nested object, restate the whole object rather than a single field:

    Request: PATCH /payment/v3/payouts/7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17 (bank details)
    {
    "beneficiary": {
    "paymentInstrument": {
    "type": "BANK_ADDRESS",
    "accountNumber": "DE89370400440532013000",
    "accountNumberFormat": "IBAN",
    "bank": {
    "bic": "COBADEFFXXX",
    "address": {
    "addressLine1": "Kaiserplatz",
    "city": "Frankfurt am Main",
    "region": "Hesse",
    "postCode": "60311",
    "country": "DE"
    }
    }
    }
    }
    }
    Response: PATCH /payment/v3/payouts/7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17 (bank details)
    {
    "id": "7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17",
    "reference": "REF-FIAT-4418",
    "type": "payment:payout",
    "status": "PENDING_QUOTE_ACCEPTANCE",
    "direction": "OUT",
    "method": "FIAT",
    "fees": {
    "customerFee": null,
    "processingFee": { "estimated": { "currency": "USD", "amount": "1.00" }, "actual": { "currency": "USD", "amount": "0.00" } }
    },
    "originator": {
    "required": { "currency": "USD", "amount": "1200.00" },
    "actual": { "currency": "USD", "amount": "0.00" },
    "walletId": "a:24072237783989:Unkx9kW:1"
    },
    "beneficiary": {
    "required": { "currency": "EUR", "amount": "1028.68" },
    "actual": { "currency": "EUR", "amount": "0.00" },
    "customerId": null,
    "customerReference": null,
    "requesterIpAddress": "172.16.254.1",
    "entity": {
    "type": "INDIVIDUAL",
    "firstName": "John",
    "lastName": "Doe",
    "dateOfBirth": "1984-06-30",
    "relationshipType": "THIRD_PARTY",
    "address": {
    "addressLine1": "Hauptstrasse 42",
    "addressLine2": null,
    "city": "Munich",
    "region": "Bavaria",
    "postCode": "80331",
    "country": "DE"
    }
    },
    "paymentInstrument": {
    "type": "BANK_ADDRESS",
    "accountNumber": "DE89370400440532013000",
    "bank": {
    "bic": "COBADEFFXXX",
    "address": {
    "addressLine1": "Kaiserplatz",
    "city": "Frankfurt am Main",
    "region": "Hesse",
    "postCode": "60311",
    "country": "DE"
    }
    }
    }
    },
    "conversion": {
    "type": "QUOTE",
    "baseRate": "0.861540",
    "allInRate": "0.857232",
    "spread": { "percentage": "0.005", "amount": "6.00", "currency": "USD" },
    "digest": "8e2b5d0c71f9a436",
    "validityDuration": "PT57M20S",
    "expiresAt": "2026-10-14T10:15:00Z",
    "priceLockDuration": "PT30S",
    "priceLockExpiresAt": "2026-10-14T09:18:10Z"
    },
    "instructions": [],
    "trackingDetails": [],
    "labels": [],
    "relatedPayments": [],
    "statusHistory": [
    { "status": "PENDING_QUOTE_ACCEPTANCE", "timestamp": "2026-10-14T09:15:00Z" }
    ],
    "flow": "default",
    "metadata": {},
    "expiryDuration": "PT1H",
    "expiresAt": "2026-10-14T10:15:00Z",
    "updatedAt": "2026-10-14T09:17:40Z",
    "createdAt": "2026-10-14T09:15:00Z"
    }

The payout now contains all required information, but it is not sent until the quote is accepted. Since a PATCH reprices the entire quote, the response includes a new conversion.digest and a new rate lock, conversion.priceLockExpiresAt, even if the amount remains unchanged. Present this response to your customer for review of the final rate, fees, and payee details before proceeding.

  1. Once your customer confirms, accept the quote by sending the POST /payment/v3/payouts/{id}/action request with "type": "ACCEPT_QUOTE":

    Request: POST /payment/v3/payouts/7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17/action
    {
    "type": "ACCEPT_QUOTE"
    }
    Response: POST /payment/v3/payouts/7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17/action (ACCEPT_QUOTE)
    {
    "id": "7c1e9a42-3b5d-4f08-9e6a-2d4b8c0f5a17",
    "reference": "REF-FIAT-4418",
    "type": "payment:payout",
    "status": "PROCESSING",
    "direction": "OUT",
    "method": "FIAT",
    "fees": {
    "customerFee": null,
    "processingFee": { "estimated": { "currency": "USD", "amount": "1.00" }, "actual": { "currency": "USD", "amount": "0.00" } }
    },
    "originator": {
    "required": { "currency": "USD", "amount": "1200.00" },
    "actual": { "currency": "USD", "amount": "1200.00" },
    "walletId": "a:24072237783989:Unkx9kW:1"
    },
    "beneficiary": {
    "required": { "currency": "EUR", "amount": "1028.68" },
    "actual": { "currency": "EUR", "amount": "0.00" },
    "customerId": null,
    "customerReference": null,
    "requesterIpAddress": "172.16.254.1",
    "entity": {
    "type": "INDIVIDUAL",
    "firstName": "John",
    "lastName": "Doe",
    "dateOfBirth": "1984-06-30",
    "relationshipType": "THIRD_PARTY",
    "address": {
    "addressLine1": "Hauptstrasse 42",
    "addressLine2": null,
    "city": "Munich",
    "region": "Bavaria",
    "postCode": "80331",
    "country": "DE"
    }
    },
    "paymentInstrument": {
    "type": "BANK_ADDRESS",
    "accountNumber": "DE89370400440532013000",
    "bank": {
    "bic": "COBADEFFXXX",
    "address": {
    "addressLine1": "Kaiserplatz",
    "city": "Frankfurt am Main",
    "region": "Hesse",
    "postCode": "60311",
    "country": "DE"
    }
    }
    }
    },
    "conversion": {
    "type": "QUOTE",
    "baseRate": "0.861540",
    "allInRate": "0.857232",
    "spread": { "percentage": "0.005", "amount": "6.00", "currency": "USD" },
    "digest": "8e2b5d0c71f9a436",
    "validityDuration": "PT57M20S",
    "expiresAt": "2026-10-14T10:15:00Z",
    "priceLockDuration": "PT30S",
    "priceLockExpiresAt": "2026-10-14T09:18:10Z"
    },
    "instructions": [],
    "trackingDetails": [],
    "labels": [],
    "relatedPayments": [],
    "statusHistory": [
    { "status": "PENDING_QUOTE_ACCEPTANCE", "timestamp": "2026-10-14T09:15:00Z" },
    { "status": "PROCESSING", "timestamp": "2026-10-14T09:18:02Z" }
    ],
    "flow": "default",
    "metadata": {},
    "expiryDuration": "PT1H",
    "expiresAt": "2026-10-14T10:15:00Z",
    "updatedAt": "2026-10-14T09:18:02Z",
    "createdAt": "2026-10-14T09:15:00Z"
    }

Accepting the quote initiates the payout; there is no separate confirmation or send step. The payout moves to PROCESSING, or to PENDING_APPROVAL if your account requires approvals. If the Verification of Payee check for a EUR payout does not return a match, the payout will remain at PENDING_VERIFICATION. See Verification of Payee (VoP).

Quotes expire with the payout

conversion.expiresAt matches the payout's own expiresAt, set by expiryDuration, and conversion.validityDuration shows the time left. Accepting or refreshing a quote after this time fails. The rate itself is locked for conversion.priceLockDuration, 30 seconds, until conversion.priceLockExpiresAt. Each reprice starts a new rate lock.

Verification of Payee (VoP)​

Verification of Payee (VoP) is a SEPA security check that compares the beneficiary's name with the name on their IBAN before a SEPA Credit Transfer or SEPA Instant Credit Transfer is sent. The beneficiary's bank reports the result back. VoP has been mandatory for euro transfers within the SEPA zone since 5 October 2025, under the Instant Payments Regulation, so it applies to your EUR payouts.

The check returns one of these results:

  • Match: the beneficiary's name matches, and the payout proceeds.
  • Partial match: the name is similar to the one on the account, but not exact. You can still send the payout at your own risk, but it may not be processed.
  • No match: the name doesn't match. You can still send the payout, but it is more likely to be rejected.
  • Not possible: the beneficiary's bank doesn't run the check.
  • Technical error: the verification service is temporarily unavailable.

In v.3, a EUR payout whose check doesn't return a match is expected to wait at PENDING_VERIFICATION until you confirm it. In v.2, the same payout returns a 202 response and doesn't exist until you confirm it. In v.3, the payout exists from the start, fully priced. The v.3 action that confirms a fiat payout, the name-match result on the response, and the confirmation window are not specified yet. For the current flow, see Verification of Payee in the v.2 guide.

Verifying a beneficiary before you create the payout, with POST /platform/v1/beneficiaries/verification and the X-Verification-Id header, works with v.2 payouts only.

Check payout status​

Send a GET request to /payment/v3/payouts/{id} at any point to see the payout's current state:

Response: GET /payment/v3/payouts/d2f7a6c1-4b83-4e59-9a0d-61c5e8b3f27a
{
"id": "d2f7a6c1-4b83-4e59-9a0d-61c5e8b3f27a",
"reference": "REF-FIAT-2091",
"type": "payment:payout",
"status": "COMPLETED",
"direction": "OUT",
"method": "FIAT",
"fees": {
"customerFee": null,
"processingFee": { "estimated": { "currency": "USDC", "amount": "1.000000" }, "actual": { "currency": "USDC", "amount": "1.000000" } }
},
"originator": {
"required": { "currency": "USDC", "amount": "991.057167" },
"actual": { "currency": "USDC", "amount": "991.057167" },
"walletId": "a:25041712093318:Qm7rTx2:1"
},
"beneficiary": {
"required": { "currency": "EUR", "amount": "850.00" },
"actual": { "currency": "EUR", "amount": "850.00" },
"customerId": null,
"customerReference": null,
"requesterIpAddress": "77.71.188.87",
"entity": {
"type": "INDIVIDUAL",
"firstName": "Anna",
"lastName": "Schmidt",
"dateOfBirth": "1990-01-15",
"relationshipType": "THIRD_PARTY",
"address": {
"addressLine1": "Leopoldstrasse 18",
"city": "Munich",
"region": "Bavaria",
"postCode": "80802",
"country": "DE"
}
},
"paymentInstrument": {
"type": "BANK_ADDRESS",
"accountNumber": "DE19700700100482917365",
"bank": {
"bic": "DEUTDEMMXXX",
"address": {
"addressLine1": "Promenadeplatz 15",
"city": "Munich",
"region": "Bavaria",
"postCode": "80333",
"country": "DE"
}
}
}
},
"conversion": {
"type": "QUOTE",
"baseRate": "0.861980",
"allInRate": "0.857670",
"spread": { "percentage": "0.005", "amount": "4.955286", "currency": "USDC" },
"validityDuration": "PT30M",
"expiresAt": "2026-10-14T11:50:05Z",
"priceLockDuration": "PT30S",
"priceLockExpiresAt": "2026-10-14T11:20:35Z"
},
"instructions": [],
"trackingDetails": [],
"labels": [],
"relatedPayments": [],
"statusHistory": [
{ "status": "PENDING_QUOTE_ACCEPTANCE", "timestamp": "2026-10-14T11:20:05Z" },
{ "status": "PROCESSING", "timestamp": "2026-10-14T11:20:05Z" },
{ "status": "COMPLETED", "timestamp": "2026-10-14T11:21:14Z" }
],
"flow": "default",
"metadata": {},
"expiryDuration": "PT30M",
"expiresAt": "2026-10-14T11:50:05Z",
"updatedAt": "2026-10-14T11:21:14Z",
"createdAt": "2026-10-14T11:20:05Z"
}

Once the payout reaches COMPLETED, all actual values are populated for originator, beneficiary, and each fee. trackingDetails[] remains empty for fiat payouts, as it is used for on-chain transactions; bank-network references, such as a wire's UETR, are not yet available in v.3. Refer to statusHistory[] for the complete payout lifecycle instead of relying on a single status value.

Handle errors​

A validation error, such as a duplicate reference, results in rejection before the payout is created:

Error response: duplicate reference
{
"requestId": "fd3b64b97db85a7ebab39d5a1fb20867",
"errorList": [
{
"parameter": "reference",
"code": "unique",
"message": "Duplicate Reference"
}
]
}

The same error format is returned if beneficiary includes both entity and contactId. Invalid bank details, such as an incorrect bank code or account number, are also rejected, and no payout is created.

If a payout fails after processing begins, no error response is returned. Instead, the payout status changes to FAILED, and the funds remain in your wallet. If the beneficiary's bank returns the funds after completion, the payout status changes to RETURNED, and the funds are credited back to your wallet. Both statuses are visible via GET requests and webhooks.

Payout webhook​

To receive notifications of payout status changes, subscribe to payment:v3:payout:status-change. Fiat and stablecoin payouts share this event, with data.method set to FIAT for fiat payouts. Use data.status for the current state and data.statusHistory[] for the full status history, rather than relying on a single value.

To refund a fiat pay-in, continue to use Refund payments. For how refunds are expected to work in v.3, see Migrate fiat payments from v.2.

Was this page helpful?