Skip to main content
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:

1. Discover the available corridors

Countries, currencies and methods are defined by CBPay. Always check the catalog:
Available corridors and methods: 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):

2. Create the payout

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.
Every payout saves the beneficiary as a contact 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).
Response 202 Accepted:
At that moment your balance already reflects the debit: total_debit moved from available into held (on the settlement_asset balance).
bank_reference — the bank’s own id for the transfer. On US ACH, wire and SWIFT it is the CBF reference returned immediately at create (the payout stays processing until the bank confirms). On other corridors it stays empty ("") until the payout is completed. It is the value the beneficiary can use to cross-check the payment with their bank, and it also appears in the payout_status_changed webhook, the PDF receipt, the payouts CSV export and the statement.

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.
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):
  • 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:

Payout statuses

Reads and history

Every payout can be read individually and the listing accepts filters:
from/to use YYYY-MM-DD (organization timezone, 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

Bank transfer in CLP. Requires RUT, bank and account:
The banks catalog (GET /v1/payouts/banks?country=CL) lists the current bank_code values.

Mandatory supporting document on USD transfers

EVERY outbound USD transfer over a bank rail (ach, wire or swift) requires an attached supporting document (invoice or receipt) — it is a requirement of the processing bank and applies to any USD corridor, not just the US one (for example, also to an international SWIFT such as PY/USD/swift).
1

Upload the document

Send the file with POST /v1/payouts/documents: raw binary body with its Content-Type (PDF, PNG, JPEG, WEBP, TXT, CSV, DOC(X) or XLS(X), up to 50 MB) and the filename in the name query param.
2

Pass it when creating the payout

The document_key travels in options.supporting_document_key. On ach/wire you can add options.document_reference_number (invoice or document reference number) — it is sent to the bank.
  • A USD bank-rail payout created without the document is rejected at creation with 400 supporting_document_required (no debit).
  • A key uploaded by another account is rejected with 400 invalid_document_key.
  • The document_key stays stored: if the create fails for another reason, you reuse it on the retry — no need to re-upload the file.

QR payout

Paying a collection QR (Bolivia, Brazil PIX) now has its own guide:

QR payout

Scan the QR for free, show your user the recipient’s data and confirm the payment in a second call - charged like a regular payout.

Common errors

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

In every case the refund is already applied — verify it with the payout_refund entry in movements.
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.

FAQ

At creation: the payout debits and holds the funds immediately. If the payout fails, the exact debited amount (fee included) is refunded automatically.
No — once dispatched to the rail it resolves to completed or failed on its own. Subscribe to payout_status_changed for the final state.
The rate quoted at creation (returned as fx_rate), frozen for that operation. Your agreed spread is already inside the rate.
Yes — set a per-account default (PUT /v1/settlement) or override per payout with settlement_asset (USDC, BTC, GOLD). Refunds return the exact settled amount, never re-quoted.
The beneficiary failed the compliance screening: the payout was not created and your idempotency_key was not consumed. Review the beneficiary data or contact your CBPay team.
Retry with the same idempotency_key: you get the original payout back (idempotency_hit: true) — never a duplicate. A new key is a new, independent payout.
US bank-rail payouts are paid by the operator by hand. Create already returns the CBF in bank_reference and stays processing until the bank confirms. Listen to payout_status_changed for the final state; a failure refunds the debit automatically.
Last modified on August 13, 2026