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

# Payouts

> Send fiat to local bank accounts, debited from your USDT balance

A payout sends money in local currency to a bank account in the destination
country. The amount converts from local currency to USDT at **your
account's rate** (the one from `GET /v1/rates`) and `usdt_amount + fee`
(the fixed fee, when configured) is debited from your balance.

This is the full lifecycle, including what happens to your balance at each
step:

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
sequenceDiagram
    autonumber
    participant App as Your app
    participant CB as CBPay
    participant Rail as Local banking rail
    App->>CB: POST /v1/payouts (idempotency_key)
    CB->>CB: Converts at your rate and debits<br/>usdt_amount + fee (available → held)
    CB-->>App: 202 processing (fx_rate, total_debit)
    CB->>Rail: Disperses in local currency
    alt The money arrives
        Rail-->>CB: Confirmed
        CB->>CB: Consumes the hold — final
        CB-->>App: Webhook payout_status_changed (completed)
    else The rail rejects
        Rail-->>CB: Rejected
        CB->>CB: Refunds the full debit to available
        CB-->>App: Webhook payout_status_changed (failed + status_code)
    end
```

## 1. Discover the available corridors

Countries, currencies and methods are defined by CBPay. Always check
the catalog:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl https://api.qbank.cl/platform/v1/payouts/methods \
  -H "Authorization: Bearer <token>"
```

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "items": [
    { "country": "CL", "currency": "CLP", "method": "bank_transfer" },
    { "country": "PE", "currency": "PEN", "method": "bank_transfer" },
    { "country": "PE", "currency": "PEN", "method": "yape" },
    { "country": "BO", "currency": "BOB", "method": "qr" }
  ],
  "meta": { "retrieved": 4 }
}
```

Available corridors and methods:

| Country   | Currency  | Methods                                                                   |
| --------- | --------- | ------------------------------------------------------------------------- |
| Chile     | CLP       | `bank_transfer`                                                           |
| Peru      | PEN       | `bank_transfer`, `yape`                                                   |
| Mexico    | MXN       | `bank_transfer` (SPEI: CLABE or debit card)                               |
| Venezuela | VES       | `bank_transfer`, `pago_movil`                                             |
| Bolivia   | BOB / USD | `bank_transfer`, `qr` (see [QR payout](#qr-payout))                       |
| Brazil    | BRL       | `pix` (by key or to account), `qr` (PIX QR — see [QR payout](#qr-payout)) |
| Ecuador   | USD       | `bank_transfer`, `deuna`, `cash_pickup`, `cnb`                            |
| Paraguay  | PYG       | `bank_transfer`                                                           |

Availability may vary; the catalog (`GET /v1/payouts/methods`) is always
the source of truth. If a country has a single method, `method` is
optional. Every method is charged the same way: your rate + fixed fee.

For bank transfers you also need the banks catalog (that is where the
beneficiary's `bank_code` comes from):

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl "https://api.qbank.cl/platform/v1/payouts/banks?country=CL" \
  -H "Authorization: Bearer <token>"
```

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "items": [
    { "code": "001", "name": "Banco de Chile" },
    { "code": "012", "name": "Banco del Estado de Chile" },
    { "code": "016", "name": "Banco de Crédito e Inversiones" }
  ],
  "meta": { "retrieved": 3 }
}
```

## 2. Create the payout

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST https://api.qbank.cl/platform/v1/payouts \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "country": "MX",
    "currency": "MXN",
    "method": "bank_transfer",
    "amount": "1500.00",
    "beneficiary": {
      "name": "Maria Lopez",
      "account_type": "clabe",
      "account_number": "012180001234567895"
    },
    "description": "Invoice 8841",
    "idempotency_key": "invoice-8841"
  }'
```

<Warning>
  `beneficiary` is a key/value object whose required fields depend on the
  corridor (RUT and bank in Chile, CLABE in Mexico, CCI in Peru, PIX key in
  Brazil, etc.). The methods catalog documents each one.
</Warning>

<Note>
  Every payout saves the beneficiary as a [contact](/en/guides/contacts)
  automatically (`"save_contact": false` to skip it). To pay them again
  without re-typing their data, send `"beneficiary_contact_id"` instead of
  `beneficiary` — their most recent saved beneficiary for that country and
  method is used (`422 no_saved_destination` if there is none).
</Note>

Response `202 Accepted`:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "payout_id": "0d4f…",
  "account_id": "…",
  "idempotency_key": "invoice-8841",
  "country": "MX",
  "currency": "MXN",
  "method": "bank_transfer",
  "local_amount": "1500.00",
  "fx_rate": "17.50",
  "usdt_amount": "85.714286",
  "fee": "0.300000",
  "total_debit": "86.014286",
  "settlement_asset": "USDT",
  "settlement_amount": "86.014286",
  "settlement_rate": "1",
  "status": "processing",
  "created_at": "2026-07-06T20:00:00Z"
}
```

At that moment your balance already reflects the debit: `total_debit` moved
from `available` into `held` (on the `settlement_asset` balance).

### Paying from another balance (`settlement_asset`)

By default the debit comes from your default settlement asset (USDT unless
you change it via `PUT /v1/settlement`). To pay a single operation from
another balance, add `settlement_asset` to the request. Example: a 100,000
CLP payout paid from the BTC balance goes through four transformations,
all recorded on the response:

1. **CLP → USDT** at your rate: `100000 / 950.25 = 105.235465 USDT`.
2. **+ fixed fee**: `105.235465 + 0.30 = 105.535465 USDT` (`total_debit`).
3. **USDT → BTC** at the effective settlement price (`settlement_rate`
   `109029.34070000`): `105.535465 / 109029.3407 = 0.00096795 BTC`
   (rounded up to the satoshi).
4. **Debit and hold in BTC**: `settlement_amount` `0.00096795` leaves your
   BTC balance; the beneficiary receives their 100,000 CLP exactly as
   always.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "country": "CL",
  "currency": "CLP",
  "local_amount": "100000",
  "fx_rate": "950.25",
  "usdt_amount": "105.235465",
  "fee": "0.300000",
  "total_debit": "105.535465",
  "settlement_asset": "BTC",
  "settlement_amount": "0.00096795",
  "settlement_rate": "109029.34070000",
  "status": "processing"
}
```

If the payout fails, the exact `settlement_amount` is refunded to your BTC
balance — never re-quoted. If the BTC/GOLD execution price is unavailable
at that moment you get `503 pricing_unavailable`, and volatile assets have
a per-operation limit (`422 settlement_limit_exceeded`; check it in
`GET /v1/settlement`).

## 3. Receive the final state

Subscribe to the `payout_status_changed` event ([webhooks](/en/webhooks)):

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "payout_id": "0d4f…",
  "account_id": "…",
  "country": "MX",
  "currency": "MXN",
  "local_amount": "1500.00",
  "usdt_amount": "85.714286",
  "total_debit": "86.014286",
  "status": "completed",
  "status_code": ""
}
```

* **`completed`**: the money arrived; the hold is consumed.
* **`failed`**: the full debit is refunded automatically (`payout_refund`
  in your ledger).

You can also query at any time:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl https://api.qbank.cl/platform/v1/payouts/0d4f… \
  -H "Authorization: Bearer <token>"
```

### Payout statuses

| Status       | Meaning                                  | Your balance                             |
| ------------ | ---------------------------------------- | ---------------------------------------- |
| `processing` | Accepted and executing on the local rail | Debit held in `held`                     |
| `completed`  | The money reached the beneficiary        | Hold consumed — final                    |
| `failed`     | The corridor rejected it or it failed    | **Full automatic refund** (amount + fee) |

## Reads and history

Every payout can be read individually and the listing accepts filters:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# One payout
curl https://api.qbank.cl/platform/v1/payouts/0d4f… \
  -H "Authorization: Bearer <token>"

# History with filters: dates, status, country and pagination
curl "https://api.qbank.cl/platform/v1/payouts?from=2026-07-01&to=2026-07-08&status=failed&country=MX&page=1&page_size=50" \
  -H "Authorization: Bearer <token>"
```

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "page": 1,
  "page_size": 50,
  "payouts": [
    {
      "payout_id": "0d4f…",
      "country": "MX",
      "currency": "MXN",
      "method": "bank_transfer",
      "local_amount": "1500.00",
      "fx_rate": "17.50",
      "usdt_amount": "85.714286",
      "fee": "0.300000",
      "total_debit": "86.014286",
      "status": "failed",
      "status_code": "core_rejected",
      "status_message": "beneficiary account does not exist",
      "created_at": "2026-07-06T20:00:00Z"
    }
  ]
}
```

`from`/`to` use `YYYY-MM-DD` (UTC, both inclusive); an invalid date
responds `400 invalid_range`.

## Examples by country

Every corridor with its exact `beneficiary`, the full request and the real
response. Rates (`fx_rate`) are illustrative — your account's rates from
`GET /v1/rates` always apply; the debit is `usdt_amount + fee` (fixed,
when configured; `0.30` here).

### Beneficiary fields per corridor

| Country | Method                | `beneficiary` fields                                                                                                  |
| ------- | --------------------- | --------------------------------------------------------------------------------------------------------------------- |
| CL      | `bank_transfer`       | `name`, `tax_id` (RUT), `bank_code`, `account_type`, `account_number`                                                 |
| PE      | `bank_transfer`       | `name`, `account_number` (20-digit CCI)                                                                               |
| PE      | `yape`                | `name`, `phone` (`51XXXXXXXXX`)                                                                                       |
| MX      | `bank_transfer`       | `name`, `account_type` (`clabe`/`debit_card`), `account_number` (+ `bank_code` for cards)                             |
| VE      | `pago_movil`          | `phone`, `bank_code` (SUDEBAN), `document_value`                                                                      |
| VE      | `bank_transfer`       | `name`, `account_number` (20 digits), `document_value`                                                                |
| BO      | `bank_transfer`       | `name`, `tax_id`, `bank_code`, `account_number`                                                                       |
| BR      | `pix`                 | `name`, `tax_id` + (`pix_key` and `pix_key_type`) or (`bank_code` ISPB, `branch_code`, `account_number`)              |
| EC      | `bank_transfer`       | `name`, `document_value` (cédula), `sender_name`, `account_number` (+ `bank_code` and `account_type` for other banks) |
| EC      | `deuna`               | `name`, `document_value`, `sender_name`, `phone` (wallet mobile number)                                               |
| EC      | `cash_pickup` / `cnb` | `name`, `document_value`, `sender_name` — the beneficiary withdraws with their ID                                     |
| PY      | `bank_transfer`       | `name` (max 35 chars), `tax_id`, `bank_code`, `account_number`                                                        |

<Tabs>
  <Tab title="Chile">
    Bank transfer in CLP. Requires RUT, bank and account:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.qbank.cl/platform/v1/payouts \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "country": "CL",
        "currency": "CLP",
        "method": "bank_transfer",
        "amount": "100000",
        "beneficiary": {
          "name": "Pedro Soto Fuentes",
          "tax_id": "12.345.678-5",
          "bank_code": "012",
          "account_type": "checking",
          "account_number": "123456789"
        },
        "description": "Supplier payment",
        "idempotency_key": "cl-prov-0091"
      }'
    ```

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "payout_id": "b3e1…",
      "country": "CL",
      "currency": "CLP",
      "method": "bank_transfer",
      "local_amount": "100000",
      "fx_rate": "925.69",
      "usdt_amount": "108.027528",
      "fee": "0.300000",
      "total_debit": "108.327528",
      "status": "processing"
    }
    ```

    The banks catalog (`GET /v1/payouts/banks?country=CL`) lists the current
    `bank_code` values.
  </Tab>

  <Tab title="Peru">
    Two methods: bank transfer (interbank CCI) and **Yape** (to a phone
    number).

    <CodeGroup>
      ```bash bank_transfer (CCI) theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "PE",
          "currency": "PEN",
          "method": "bank_transfer",
          "amount": "1000.00",
          "beneficiary": {
            "name": "Rosa Alvarez Diaz",
            "account_number": "00219300123456789012"
          },
          "idempotency_key": "pe-cci-3310"
        }'
      ```

      ```bash yape (phone) theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "PE",
          "currency": "PEN",
          "method": "yape",
          "amount": "150.00",
          "beneficiary": {
            "name": "Luis Ramos Vega",
            "phone": "51987654321"
          },
          "idempotency_key": "pe-yape-8874"
        }'
      ```
    </CodeGroup>

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "payout_id": "c7a2…",
      "country": "PE",
      "currency": "PEN",
      "method": "yape",
      "local_amount": "150.00",
      "fx_rate": "3.40",
      "usdt_amount": "44.117648",
      "fee": "0.300000",
      "total_debit": "44.417648",
      "status": "completed"
    }
    ```

    For `yape` the phone uses the `51XXXXXXXXX` format (11 digits with country
    code). The result is usually synchronous.
  </Tab>

  <Tab title="Mexico">
    SPEI in MXN, to a CLABE (18 digits) or a debit card:

    <CodeGroup>
      ```bash CLABE theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "MX",
          "currency": "MXN",
          "method": "bank_transfer",
          "amount": "1500.00",
          "beneficiary": {
            "name": "Maria Lopez",
            "account_type": "clabe",
            "account_number": "012180001234567895"
          },
          "idempotency_key": "mx-clabe-8841"
        }'
      ```

      ```bash Debit card theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "MX",
          "currency": "MXN",
          "method": "bank_transfer",
          "amount": "800.00",
          "beneficiary": {
            "name": "Jorge Herrera",
            "account_type": "debit_card",
            "account_number": "4152313412341234",
            "bank_code": "40012"
          },
          "idempotency_key": "mx-card-1102"
        }'
      ```
    </CodeGroup>

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "payout_id": "0d4f…",
      "country": "MX",
      "currency": "MXN",
      "method": "bank_transfer",
      "local_amount": "1500.00",
      "fx_rate": "17.50",
      "usdt_amount": "85.714286",
      "fee": "0.300000",
      "total_debit": "86.014286",
      "status": "processing"
    }
    ```

    With a CLABE the destination bank derives from its leading digits; with a
    card, `bank_code` is required.
  </Tab>

  <Tab title="Venezuela">
    Two methods: **Pago Móvil** (phone + bank + ID) and bank transfer
    (20-digit account):

    <CodeGroup>
      ```bash pago_movil theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "VE",
          "currency": "VES",
          "method": "pago_movil",
          "amount": "2000.00",
          "beneficiary": {
            "phone": "04141234567",
            "bank_code": "0102",
            "document_value": "V12345678"
          },
          "idempotency_key": "ve-pm-5567"
        }'
      ```

      ```bash bank_transfer theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "VE",
          "currency": "VES",
          "method": "bank_transfer",
          "amount": "5000.00",
          "beneficiary": {
            "name": "Carmen Delgado",
            "account_number": "01020123456789012345",
            "document_value": "V87654321"
          },
          "idempotency_key": "ve-bank-7810"
        }'
      ```
    </CodeGroup>

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "payout_id": "e9b4…",
      "country": "VE",
      "currency": "VES",
      "method": "pago_movil",
      "local_amount": "2000.00",
      "fx_rate": "666.00",
      "usdt_amount": "3.003004",
      "fee": "0.300000",
      "total_debit": "3.303004",
      "status": "completed"
    }
    ```

    `bank_code` uses SUDEBAN codes; for `bank_transfer` it can derive from the
    account's first 4 digits.
  </Tab>

  <Tab title="Bolivia">
    ACH transfer in BOB or USD (besides the [QR](#qr-payout)):

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.qbank.cl/platform/v1/payouts \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "country": "BO",
        "currency": "BOB",
        "method": "bank_transfer",
        "amount": "1382.00",
        "beneficiary": {
          "name": "Juan Quispe Mamani",
          "tax_id": "4567890",
          "bank_code": "1016",
          "account_number": "1234567890"
        },
        "idempotency_key": "bo-ach-2204"
      }'
    ```

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "payout_id": "f2c8…",
      "country": "BO",
      "currency": "BOB",
      "method": "bank_transfer",
      "local_amount": "1382.00",
      "fx_rate": "6.91",
      "usdt_amount": "200.000000",
      "fee": "0.300000",
      "total_debit": "200.300000",
      "status": "processing"
    }
    ```

    For USD send `currency: "USD"` with the same structure.
  </Tab>

  <Tab title="Brazil">
    PIX by key (besides the [PIX QR](#qr-payout)):

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.qbank.cl/platform/v1/payouts \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "country": "BR",
        "currency": "BRL",
        "method": "pix",
        "amount": "350.00",
        "beneficiary": {
          "name": "João da Silva",
          "tax_id": "123.456.789-09",
          "pix_key_type": "cpf",
          "pix_key": "12345678909"
        },
        "idempotency_key": "br-pix-3321"
      }'
    ```

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "payout_id": "a6d1…",
      "country": "BR",
      "currency": "BRL",
      "method": "pix",
      "local_amount": "350.00",
      "fx_rate": "5.13",
      "usdt_amount": "68.226121",
      "fee": "0.300000",
      "total_debit": "68.526121",
      "status": "processing"
    }
    ```

    `pix_key_type`: `cpf`, `cnpj`, `phone`, `email` or `evp` (random key).

    **PIX to account (no key)** — when the beneficiary does not have (or share)
    a PIX key, send their bank details; it arrives just as fast (same PIX rail,
    24/7):

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.qbank.cl/platform/v1/payouts \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "country": "BR",
        "currency": "BRL",
        "method": "pix",
        "amount": "350.00",
        "beneficiary": {
          "name": "Empresa Exemplo Ltda",
          "tax_id": "19.385.062/0001-20",
          "bank_code": "45678923",
          "branch_code": "1",
          "account_number": "765432",
          "account_type": "CACC"
        },
        "idempotency_key": "br-pix-acct-3322"
      }'
    ```

    * `bank_code` is the destination bank's **ISPB** (8 digits), `branch_code`
      the agency, and `account_type` the account type (`CACC` checking —
      default —, `SVGS` savings, `TRAN` payment account, `SLRY` salary).
    * The final status arrives through the `payout_status_changed` webhook
      (continuous reconciliation against the rail); check on demand with
      `GET /v1/payouts/{id}`.
  </Tab>

  <Tab title="Ecuador">
    Remittances in **USD** (1 to 10,000 per operation, up to 2 decimals) with
    four methods: bank transfer, the **DE UNA** wallet (by mobile number),
    **cash pickup** at a branch (`cash_pickup`) and cash at a **non-bank
    correspondent** (`cnb`). This is a remittance corridor: besides the
    beneficiary, the rail requires the **sender's** data (who originates the
    payment), sent flat inside the same `beneficiary` object with the
    `sender_*` prefix.

    <CodeGroup>
      ```bash bank_transfer (to account) theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "EC",
          "currency": "USD",
          "method": "bank_transfer",
          "amount": "250.00",
          "beneficiary": {
            "name": "Carlos Andrade Vera",
            "document_value": "1712345678",
            "account_number": "2203456789",
            "sender_name": "Ana Torres Silva",
            "sender_document_value": "V23456789",
            "sender_country": "US"
          },
          "idempotency_key": "ec-bank-4471"
        }'
      ```

      ```bash deuna (wallet) theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "EC",
          "currency": "USD",
          "method": "deuna",
          "amount": "80.00",
          "beneficiary": {
            "name": "Lucia Paredes Mora",
            "document_value": "0923456781",
            "phone": "0998765432",
            "sender_name": "Ana Torres Silva"
          },
          "idempotency_key": "ec-deuna-5520"
        }'
      ```

      ```bash cash_pickup (branch) theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "EC",
          "currency": "USD",
          "method": "cash_pickup",
          "amount": "120.00",
          "beneficiary": {
            "name": "Miguel Zambrano Loor",
            "document_value": "1309876543",
            "sender_name": "Ana Torres Silva"
          },
          "idempotency_key": "ec-cash-6612"
        }'
      ```

      ```bash cnb (correspondent) theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST https://api.qbank.cl/platform/v1/payouts \
        -H "Authorization: Bearer <token>" \
        -H "Content-Type: application/json" \
        -d '{
          "country": "EC",
          "currency": "USD",
          "method": "cnb",
          "amount": "60.00",
          "beneficiary": {
            "name": "Rosa Cedeño Vera",
            "document_value": "0801234567",
            "sender_name": "Ana Torres Silva"
          },
          "idempotency_key": "ec-cnb-7703"
        }'
      ```
    </CodeGroup>

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "payout_id": "9f3a…",
      "country": "EC",
      "currency": "USD",
      "method": "bank_transfer",
      "local_amount": "250.00",
      "fx_rate": "1",
      "usdt_amount": "250.000000",
      "fee": "0.300000",
      "total_debit": "250.300000",
      "status": "processing"
    }
    ```

    * Ecuador is dollarized: the local currency IS the USD (`fx_rate: "1"`).
    * `document_value` is the beneficiary's cédula; `document_type` accepts
      `IDCD` (national ID, default), `CCPT` (passport) or `TXID` (RUC).
    * On `bank_transfer`, omitting `bank_code` targets an account at the
      corridor's issuing bank; for **another bank** send the `bank_code` from
      the catalog (`GET /v1/payouts/banks?country=EC`) plus `account_type`
      (`checking` or `savings`).
    * Optional structured names (`given_name`, `middle_name`,
      `first_surname`, `second_surname` and their `sender_*` counterparts):
      send them when you have them — they take precedence over the automatic
      split of `name`.
    * The final status arrives via the `payout_status_changed` webhook (with
      periodic reconciliation as backup).
  </Tab>

  <Tab title="Paraguay">
    Bank transfer in PYG:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.qbank.cl/platform/v1/payouts \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "country": "PY",
        "currency": "PYG",
        "method": "bank_transfer",
        "amount": "500000",
        "beneficiary": {
          "name": "Sofia Benitez",
          "tax_id": "4123456",
          "bank_code": "0011",
          "account_number": "600123456"
        },
        "idempotency_key": "py-bank-9917"
      }'
    ```

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "payout_id": "d4e7…",
      "country": "PY",
      "currency": "PYG",
      "method": "bank_transfer",
      "local_amount": "500000",
      "fx_rate": "6055.76",
      "usdt_amount": "82.566020",
      "fee": "0.300000",
      "total_debit": "82.866020",
      "status": "processing"
    }
    ```

    `name` accepts up to 35 characters in this corridor.
  </Tab>
</Tabs>

## QR payout

In Bolivia (the local interoperable QR) and Brazil (**PIX QR**, including
the "copia e cola" code) you can also **pay a collection QR** in two
steps: scan and confirm. Scanning is **free**; you are only charged on
confirm, exactly like a regular payout (your rate + fixed fee). Without
`country`/`currency` Bolivia (BOB) is assumed; for Brazil send
`country: "BR"` and `currency: "BRL"`.

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart LR
    scan["1. POST qr/scan<br/>(free)"] --> data["Recipient data<br/>+ provider_reference"]
    data --> userConfirms{"Does the user<br/>confirm?"}
    userConfirms -->|"Yes"| confirm["2. POST qr/confirm<br/>(charged: your rate + fixed)"]
    userConfirms -->|"No"| done["Nothing was charged"]
    confirm --> result{"Synchronous<br/>result"}
    result -->|"completed"| paid["Paid — debit consumed"]
    result -->|"failed"| refund["Full automatic<br/>refund"]
```

### 1. Scan the QR (free)

<Tabs>
  <Tab title="Bolivia">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.qbank.cl/platform/v1/payouts/qr/scan \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "qr_payload": "<QR content>",
        "currency": "BOB"
      }'
    ```

    Returns the recipient's data so the user can confirm who they are paying:

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "scan_id": "…",
      "provider_reference": "…",
      "beneficiary_name": "Juan Quispe",
      "destination_account": "…",
      "amount": "700.00",
      "currency": "BOB",
      "glosa": "",
      "status": "…"
    }
    ```
  </Tab>

  <Tab title="Brazil (PIX QR)">
    `qr_payload` takes the raw PIX QR content (the EMV BR Code) **or the
    "copia e cola" code** — they are the same string:

    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.qbank.cl/platform/v1/payouts/qr/scan \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "country": "BR",
        "currency": "BRL",
        "qr_payload": "00020126360014br.gov.bcb.pix0114+5511998765432520400005303986540575.005802BR5913LOJA DA MARIA6009SAO PAULO62110507PED423163040BF9"
      }'
    ```

    The scan decodes the BR Code locally (validating its checksum) and returns
    the destination PIX key, the merchant name and the amount when the QR
    carries a fixed one:

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    {
      "scan_id": "PIXSCAN-…",
      "provider_reference": "<the same EMV payload>",
      "beneficiary_name": "LOJA DA MARIA",
      "destination_account": "+5511998765432",
      "amount": "75.00",
      "currency": "BRL",
      "glosa": "",
      "status": "scanned"
    }
    ```

    * An empty `amount` means an **open-amount** QR: you decide how much to pay
      on confirm. With a fixed amount, the confirm must send exactly that
      amount.
    * **Static** PIX QRs are supported (the printed/reusable ones with the key
      embedded). A **dynamic** QR (payload carrying the PSP's URL instead of a
      key) answers `400` with
      `dynamic pix qr codes are not supported yet` — ask the beneficiary for
      their PIX key and use the [`pix`](#examples-by-country) method.
    * A tampered or truncated payload answers `400` (invalid CRC checksum).
  </Tab>
</Tabs>

### 2. Confirm the payment (charged here)

<Tabs>
  <Tab title="Bolivia">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.qbank.cl/platform/v1/payouts/qr/confirm \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "provider_reference": "<from the scan>",
        "amount": "700.00",
        "currency": "BOB",
        "description": "QR lunch payment",
        "idempotency_key": "qr-2026-07-07-a"
      }'
    ```
  </Tab>

  <Tab title="Brazil (PIX QR)">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -X POST https://api.qbank.cl/platform/v1/payouts/qr/confirm \
      -H "Authorization: Bearer <token>" \
      -H "Content-Type: application/json" \
      -d '{
        "country": "BR",
        "currency": "BRL",
        "provider_reference": "<from the scan>",
        "amount": "75.00",
        "description": "Order 4231",
        "idempotency_key": "qr-br-2026-07-16-a"
      }'
    ```

    * `amount` is always required: with a fixed-amount QR it must match
      exactly — otherwise you get `422` with the payout in `status: failed`
      (`status_message: "amount mismatch: the qr requires exactly 75.00 BRL"`)
      and the **refund already applied**; fix the amount and retry with a new
      key. With an open-amount QR whatever you send is what gets paid.
    * A **static PIX QR is reusable by design** (a shop's printed QR gets paid
      many times): you can pay it again with a different `idempotency_key`. A
      failed attempt **does not burn the QR**.
    * The payment travels through the same PIX rail as the `pix` method
      (24/7); the QR's `txid` goes with it so the merchant reconciles
      automatically.
  </Tab>
</Tabs>

* `usdt_amount + fixed fee` is debited at **your rate**, just like a
  `bank_transfer`.
* The result is **synchronous**: the response already carries the final
  state (`completed`, or `failed` with an automatic refund) — no waiting.
* Retries with the same `idempotency_key` return the original payout. In
  Bolivia the scan reference is single-use (a scanned QR can only be paid
  once); in Brazil a static PIX QR is reusable and each payment carries its
  own key.

## Common errors

| HTTP | `error`                        | What to do                                                                                                                                                                                           |
| ---- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `idempotency_key_required`     | Send the key in body or header                                                                                                                                                                       |
| 400  | `beneficiary_required`         | Include the `beneficiary` object                                                                                                                                                                     |
| 402  | `insufficient_funds`           | Fund the account; the payout was not created                                                                                                                                                         |
| 403  | `account_blocked`              | The account is not active; contact the CBPay team                                                                                                                                                    |
| 403  | `service_disabled`             | Payouts is not enabled for your account — see [services](/en/concepts/services)                                                                                                                      |
| 403  | `compliance_hold`              | The payout was held by the platform's compliance controls and was NOT created (no debit). By policy the exact reason is not disclosed — contact support with the timestamp; see [errors](/en/errors) |
| 422  | `currency_not_supported`       | No FX rate for that currency                                                                                                                                                                         |
| 422  | (payout with `status: failed`) | The corridor rejected the data; the debit was already refunded — fix `beneficiary` and retry with a new key                                                                                          |
| 503  | `channel_unavailable`          | The payout channel is temporarily unavailable; retry later with the SAME `idempotency_key`                                                                                                           |
| 503  | `compliance_check_unavailable` | The compliance check could not be evaluated; the payout was NOT created — retry with the SAME `idempotency_key`                                                                                      |

## Immediate rejection vs later failure

If the processor rejects the payout at creation, you receive `422` with the
object in `status: failed` and the refund already applied. If it fails later
(e.g. the destination account does not exist), the webhook arrives with
`status: failed` and the automatic refund happens at that moment.

### Reading `status_code` on a failed payout

| `status_code`         | Meaning                                                                                           | Action                                                                     |
| --------------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `core_rejected`       | The processor rejected the operation at creation (invalid beneficiary data, corridor unavailable) | Read `status_message`, fix the data and create a new payout with a new key |
| `channel_unavailable` | The payout channel became temporarily unavailable                                                 | Retry later; the refund (if a debit happened) is already applied           |
| *another code*        | Later rejection by the banking rail (e.g. destination account closed)                             | Same: fix the data and create a new operation                              |
| *(empty)*             | Generic corridor failure                                                                          | Check `status_message`; if unclear, contact support with the `payout_id`   |

In every case the refund is already applied — verify it with the
`payout_refund` entry in
[movements](/en/concepts/movements-reconciliation).

<Note>
  A payout in `processing` cannot be cancelled through the API: the rail
  already has it. Wait for the final state via webhook or `GET` — it always
  arrives, with an automatic refund on failure.
</Note>
