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

# Create a bank payout

> POST /v1/bank/payout - execute a quoted payout to any bank account, including a third party's.

Creates the payout and answers with where the user sends stablecoins. The
destination may be **the user's own account or somebody else's** - a payout is a
transfer to a named beneficiary, not a withdrawal from a balance.

See [Payouts](/products/payouts) for the order and
[POST /v1/bank/payout/quote](/api-reference/bank-payout-quote) for the price.

<Note>
  Needs the **bank-payouts permission** on your API key.
</Note>

## Request

<ParamField body="quoteId" type="string" required>
  From the quote. Expired quotes are refused rather than silently repriced.
</ParamField>

<ParamField body="accountId" type="string" required>
  The user paying out - the one whose identity result we hold and whose wallet
  funds this. Not the beneficiary.
</ParamField>

<ParamField body="beneficiary" type="object" required>
  Who gets paid. Always carries `name` and a `schema` that names the shape of the
  rest - the fields required differ per rail and are validated against the schema,
  so a field the schema does not define is refused rather than ignored.

  | `schema`      | Used for                          | Fields beyond `name`                                                               |
  | ------------- | --------------------------------- | ---------------------------------------------------------------------------------- |
  | `bank_sepa`   | EUR over SEPA                     | `accountType`, `firstName`, `lastName`, `IBAN`                                     |
  | `bank_uk`     | GBP over Faster Payments          | Account and sort code                                                              |
  | `bank_us`     | USD over ACH or Wire              | `bankName`, `accountName`, `accountNumber`, `routingNumber`, `beneficiaryAddress`  |
  | `bank_swift`  | USD internationally               | `accountType`, `companyName`, `bankName`, `swiftCode`, `accountNumber`, `currency` |
  | `bank_br_pix` | BRL over PIX                      | PIX key                                                                            |
  | `bank_mexico` | MXN over SPEI                     | CLABE                                                                              |
  | `bank_africa` | NGN and other local African banks | `financialInstitutionId`, `accountNumber`, `accountName`                           |
  | `momo_africa` | Mobile money                      | Wallet identifier                                                                  |
  | `evm`         | Stablecoin to a wallet            | `address`                                                                          |

  `bank_us` needs a full `beneficiaryAddress` (street, city, postal code, country,
  state) - it is the one schema people are surprised by, and a payout without it
  is refused rather than queued.
</ParamField>

<ParamField body="purpose" type="string">
  Free-text reason for the transfer, passed to the receiving bank where the rail
  carries one. Some corridors require it; the quote's `rail` tells you which.
</ParamField>

<ParamField body="reference" type="string">
  Your own idempotency key, up to 64 characters. Repeating a request with the same
  `reference` returns the original payout instead of sending money twice. **Send
  one** - on this endpoint a retry without it is a second transfer.
</ParamField>

## Response

<ResponseField name="id" type="string">
  The payout id. Poll with
  [POST /v1/bank/payout/status](/api-reference/bank-payout-status).
</ResponseField>

<ResponseField name="depositAddress" type="string">
  Where the user sends the stablecoins - a contract we control, derived per
  payout. **Single-use.**
</ResponseField>

<ResponseField name="depositAmount" type="string">
  The exact amount to send.
</ResponseField>

<ResponseField name="chain" type="number">
  The chain `depositAddress` lives on. Sending on any other chain loses the funds.
</ResponseField>

<ResponseField name="status" type="string">
  `pending` on creation.
</ResponseField>

<ResponseField name="expiresAt" type="string">
  ISO 8601. Stablecoins arriving after this convert at the rate current on
  arrival, not the quoted one.
</ResponseField>

## How the user sends

A plain ERC-20 transfer of `depositAmount` to `depositAddress` is all that is
needed - no approval, no contract call, no custom ABI. The address is derived for
this payout alone, which is how the arriving money is attributed without the
sender doing anything special.

Nothing is custodial before that transfer confirms, and Rheon never holds the
user's key. Your wallet builds and signs the transfer exactly as it would any
other.

<Warning>
  **One address, one payout.** Sending to a spent address leaves money with no order
  to attribute it to. Ask for a new payout rather than reusing an address, even for
  the same beneficiary and amount.
</Warning>

<Note>
  The beneficiary's bank sees a transfer from our banking partner's account carrying
  the reference we return, not from the user's own virtual account. Whether a given
  receiving bank displays the reference varies by rail.
</Note>

<Warning>
  **A beneficiary cannot be edited once created** - a correction means creating a
  new one, and one with a payment in flight cannot be removed at all. Treat the
  details as final at the moment you send them, and validate them in your own UI
  before they reach us.
</Warning>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "$RHEON_API/v1/bank/payout" \
    -H "Authorization: Bearer $RHEON_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "quoteId": "bpq_2e90c4a71f",
      "accountId": "acct_8f2c91d0a4",
      "beneficiary": {
        "name": "Ana Ribeiro",
        "schema": "bank_sepa",
        "accountType": "individual",
        "firstName": "Ana",
        "lastName": "Ribeiro",
        "IBAN": "IE25XXXX99035504017602"
      },
      "purpose": "invoice 2026-114",
      "reference": "payout-2026-09-02-115"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "bpo_77c2e1f430",
    "depositAddress": "0x2C7b90Ee4A1d8F63c05B7a9e21D4f8016Ba3cE77",
    "depositAmount": "1000.00",
    "chain": 42161,
    "status": "pending",
    "expiresAt": "2026-09-02T18:14:12Z"
  }
  ```
</ResponseExample>

## Errors

| HTTP | `code`              | When                                                                              |
| ---- | ------------------- | --------------------------------------------------------------------------------- |
| 400  | `invalid_request`   | A field is missing or malformed, or the beneficiary fields do not match the rail. |
| 401  | `unauthorized`      | Missing, malformed, or unknown API key.                                           |
| 403  | `permission_denied` | Your key does not carry the bank-payouts permission.                              |
| 404  | `account_not_found` | No such `accountId` under your key.                                               |
| 409  | `quote_expired`     | The quote is past `expiresAt`. Quote again.                                       |
| 422  | `requires_action`   | The user needs a higher verification tier before paying out.                      |
| 429  | `rate_limited`      | Over your key's rate limit.                                                       |
| 502  | `upstream_error`    | The banking partner is unavailable.                                               |
| 500  | `internal`          | Unexpected server error.                                                          |
