Fiat Payouts API
Disburse local currency to a beneficiary's bank account, funded from your balance.
Rolling out. Local-currency payout rails are being enabled progressively through licensed payout partners. In production these endpoints return 503 provider_unavailable until your organization's payout corridor is switched on. The contract below is stable — integrate against it now. See the flow of funds.A fiat payout sends local currency to a beneficiary through a licensed payout partner. It is funded from your organization's USDC balance — the same balance your collections settle into. Caibo screens the payout, converts from your balance, and the partner credits the beneficiary's local account.
The supported destination countries and the beneficiary fields each one requires are returned by the catalog (GET /v1/countries, GET /v1/payment-methods) — they are not hard-coded here.
Create a fiat payout
POST /v1/fiat-payouts — Scope: payouts:write
Creates a fiat payout and starts its lifecycle: it is screened, then (if it clears and is within the auto-approval limit) sent to the payout partner for delivery.
Headers
| Header | Required | Description |
|---|---|---|
X-API-Key | Yes | Your API key. |
Content-Type | Yes | application/json |
Idempotency-Key | Yes | A unique value per logical payout. Retries with the same key return the original payout. See Idempotency. |
Body parameters
| Field | Type | Required | Description |
|---|---|---|---|
amount | string | Yes | Decimal amount > 0 in the destination currency, e.g. "250000.00". |
currency | string | Yes | Destination local currency, ISO 4217, e.g. COP. Must be enabled for country. |
country | string | Yes | Destination country, ISO-3166 alpha-2, e.g. CO. Must be in GET /v1/countries. |
beneficiary | object | Yes | Who receives the funds. See sub-fields below. |
beneficiary.name | string | Yes | Full legal name of the beneficiary. |
beneficiary.account | object | Yes | Local account details. Required keys vary by country/method — read them from GET /v1/payment-methods. |
metadata | object | No | Arbitrary key/value pairs echoed back on the payout. |
beneficiary.accountis intentionally open: a country may requireaccount_number+institution+document_id, another an IBAN or a CLABE. Query the catalog for the exact required fields per country before you build the form.
Request
curl https://api.caiboglobal.com/v1/fiat-payouts \
-H "X-API-Key: $CAIBO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8f7e6d5c-4b3a-2c1d-0e9f-8a7b6c5d4e3f" \
-d '{
"amount": "250000.00",
"currency": "COP",
"country": "CO",
"beneficiary": {
"name": "Maria Gomez",
"account": {
"type": "bank_account",
"institution": "007",
"account_number": "1234567890",
"document_id": "CC-79000000"
}
},
"metadata": { "invoice_id": "INV-2043" }
}'The example country/currency above is illustrative. Use the values returned by GET /v1/countries for corridors enabled on your organization.
Response — 201 Created
Returns the fiat payout. beneficiary.account.account_number is masked in responses. If the amount exceeds your auto-approval limit, the status is pending_approval and the HTTP status is 202 Accepted instead of 201.
{
"id": "fpo_9a8b7c6d5e4f",
"object": "fiat_payout",
"status": "processing",
"mode": "live",
"amount": "250000.00",
"currency": "COP",
"country": "CO",
"beneficiary": {
"name": "Maria Gomez",
"account": { "type": "bank_account", "institution": "007", "account_number": "******7890" }
},
"screening_status": "clear",
"tracking": { "reference": "CAI-FP-9A8B7C6D", "estimated_settlement": "2026-07-23T18:00:00Z" },
"metadata": { "invoice_id": "INV-2043" },
"created_at": "2026-07-23T14:03:00Z"
}Behavior
- Funded from your balance. The payout draws from your organization's USDC balance (the settlement rail). If the balance is below the required amount, it returns
402 insufficient_balance. - Screening runs first, in-line. The beneficiary is screened before anything is sent. A flagged beneficiary yields
403 screening_blockedand a payout with statusblocked; no funds move. See Compliance & screening. - Auto-approval. Amounts within your organization's auto-approval limit send immediately; larger ones return
202with statuspending_approvaland wait for a manual approval. - Idempotent. Reusing the
Idempotency-Keywith the same body returns the original payout; with a different body it returns409 idempotency_conflict. - Webhooks. A successful create fires
fiat_payout.processingand finallyfiat_payout.completed(orfiat_payout.failedwith a refund). A blocked payout firesfiat_payout.blocked.
Errors
| HTTP | type | code | When |
|---|---|---|---|
| 400 | invalid_request_error | bad_request | Missing Idempotency-Key, malformed body, or an invalid amount. |
| 401 | authentication_error | api_key_missing / api_key_invalid | No key, or an unknown/revoked key. |
| 403 | permission_error | scope_insufficient | The key lacks payouts:write. |
| 403 | compliance_error | kyb_required | Live mode with an unverified business. |
| 403 | compliance_error | screening_blocked | The beneficiary was blocked by screening. |
| 403 | compliance_error | limit_exceeded | The payout would breach a per-payout, daily, or monthly limit. |
| 402 | invalid_request_error | insufficient_balance | Balance below the required amount. |
| 409 | invalid_request_error | idempotency_conflict | The idempotency key was reused with a different request. |
| 422 | invalid_request_error | unsupported_country | The country/currency corridor is not enabled, or required beneficiary fields are missing. |
| 429 | rate_limit_error | rate_limited | Too many requests. Back off and retry. |
| 503 | api_error | provider_unavailable | The payout corridor is not yet enabled for your organization (rolling out) or is temporarily unavailable. |
Fiat payout state machine
A fiat payout moves through the same shape as a stablecoin payout: screened, then delivered.
pending ──▶ screening ──▶ processing ──▶ completed (beneficiary credited)
│ │
▼ ▼
blocked failed (funds refunded to your balance)
(cancel is possible up to — but not during — processing) ──▶ cancelled| Status | Meaning | Terminal? |
|---|---|---|
pending | Created and accepted; about to be screened. | No |
screening | The beneficiary is being screened (sanctions + blacklist). | No |
processing | Sent to the payout partner for delivery. | No |
completed | The beneficiary's local account was credited. | Yes |
blocked | Screening blocked the beneficiary. The payout was not sent. | Yes |
failed | Delivery failed or was returned. Funds were refunded to your balance. | Yes |
cancelled | You cancelled it before it started processing. | Yes |
pending_approval | Cleared screening but exceeds the org's auto-approval limit; held for manual approval. | No |
Webhooks
Register for these on your webhook endpoints. Each delivery is signed with Caibo-Signature; verify it as described in the Webhooks guide.
| Event | Fires when | Status |
|---|---|---|
fiat_payout.processing | The payout is sent to the payout partner. | processing |
fiat_payout.completed | The beneficiary's account has been credited. | completed |
fiat_payout.failed | Delivery failed or was returned (funds refunded). | failed |
fiat_payout.blocked | Screening blocked the beneficiary (no funds moved). | blocked |
{
"event": "fiat_payout.completed",
"object": "fiat_payout",
"id": "fpo_9a8b7c6d5e4f",
"status": "completed",
"amount": "250000.00",
"currency": "COP",
"country": "CO",
"mode": "live",
"created_at": "2026-07-23T14:03:00Z"
}The webhook payload is a snapshot. For anything critical, re-fetch the fiat payout with GET /v1/fiat-payouts/{id} to confirm its current state.Retrieve a fiat payout
GET /v1/fiat-payouts/{id} — Scope: payouts:read
Fetches a single fiat payout by id. Returns 404 resource_missing if it doesn't exist or isn't yours.
curl https://api.caiboglobal.com/v1/fiat-payouts/fpo_9a8b7c6d5e4f \
-H "X-API-Key: $CAIBO_API_KEY"Errors
| HTTP | type | code | When |
|---|---|---|---|
| 401 | authentication_error | api_key_missing / api_key_invalid | No key, or an unknown/revoked key. |
| 403 | permission_error | scope_insufficient | The key lacks payouts:read. |
| 404 | invalid_request_error | resource_missing | No such fiat payout for your organization. |
List fiat payouts
GET /v1/fiat-payouts — Scope: payouts:read
Returns your organization's fiat payouts, newest first, cursor-paginated.
Query parameters
| Parameter | Type | Description |
|---|---|---|
limit | integer | Page size, 1–100. Defaults to 25. |
starting_after | string | A fiat payout id; returns the page after it. See Pagination. |
status | string | Filter by a single status, e.g. completed. |
country | string | Filter by destination country, ISO-3166 alpha-2. |
Request
curl "https://api.caiboglobal.com/v1/fiat-payouts?limit=25&status=completed" \
-H "X-API-Key: $CAIBO_API_KEY"Response — 200 OK
{
"object": "list",
"data": [
{
"id": "fpo_9a8b7c6d5e4f",
"object": "fiat_payout",
"status": "completed",
"mode": "live",
"amount": "250000.00",
"currency": "COP",
"country": "CO",
"created_at": "2026-07-23T14:03:00Z"
}
],
"has_more": true,
"next_cursor": "fpo_9a8b7c6d5e4f"
}Errors
| HTTP | type | code | When |
|---|---|---|---|
| 401 | authentication_error | api_key_missing / api_key_invalid | No key, or an unknown/revoked key. |
| 403 | permission_error | scope_insufficient | The key lacks payouts:read. |
| 429 | rate_limit_error | rate_limited | Too many requests. |