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

HeaderRequiredDescription
X-API-KeyYesYour API key.
Content-TypeYesapplication/json
Idempotency-KeyYesA unique value per logical payout. Retries with the same key return the original payout. See Idempotency.

Body parameters

FieldTypeRequiredDescription
amountstringYesDecimal amount > 0 in the destination currency, e.g. "250000.00".
currencystringYesDestination local currency, ISO 4217, e.g. COP. Must be enabled for country.
countrystringYesDestination country, ISO-3166 alpha-2, e.g. CO. Must be in GET /v1/countries.
beneficiaryobjectYesWho receives the funds. See sub-fields below.
beneficiary.namestringYesFull legal name of the beneficiary.
beneficiary.accountobjectYesLocal account details. Required keys vary by country/method — read them from GET /v1/payment-methods.
metadataobjectNoArbitrary key/value pairs echoed back on the payout.
beneficiary.account is intentionally open: a country may require account_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

bash
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.

json
{
  "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_blocked and a payout with status blocked; no funds move. See Compliance & screening.
  • Auto-approval. Amounts within your organization's auto-approval limit send immediately; larger ones return 202 with status pending_approval and wait for a manual approval.
  • Idempotent. Reusing the Idempotency-Key with the same body returns the original payout; with a different body it returns 409 idempotency_conflict.
  • Webhooks. A successful create fires fiat_payout.processing and finally fiat_payout.completed (or fiat_payout.failed with a refund). A blocked payout fires fiat_payout.blocked.

Errors

HTTPtypecodeWhen
400invalid_request_errorbad_requestMissing Idempotency-Key, malformed body, or an invalid amount.
401authentication_errorapi_key_missing / api_key_invalidNo key, or an unknown/revoked key.
403permission_errorscope_insufficientThe key lacks payouts:write.
403compliance_errorkyb_requiredLive mode with an unverified business.
403compliance_errorscreening_blockedThe beneficiary was blocked by screening.
403compliance_errorlimit_exceededThe payout would breach a per-payout, daily, or monthly limit.
402invalid_request_errorinsufficient_balanceBalance below the required amount.
409invalid_request_erroridempotency_conflictThe idempotency key was reused with a different request.
422invalid_request_errorunsupported_countryThe country/currency corridor is not enabled, or required beneficiary fields are missing.
429rate_limit_errorrate_limitedToo many requests. Back off and retry.
503api_errorprovider_unavailableThe 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.

text
pending ──▶ screening ──▶ processing ──▶ completed   (beneficiary credited)
                │              │
                ▼              ▼
             blocked        failed  (funds refunded to your balance)

(cancel is possible up to — but not during — processing) ──▶ cancelled
StatusMeaningTerminal?
pendingCreated and accepted; about to be screened.No
screeningThe beneficiary is being screened (sanctions + blacklist).No
processingSent to the payout partner for delivery.No
completedThe beneficiary's local account was credited.Yes
blockedScreening blocked the beneficiary. The payout was not sent.Yes
failedDelivery failed or was returned. Funds were refunded to your balance.Yes
cancelledYou cancelled it before it started processing.Yes
pending_approvalCleared 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.

EventFires whenStatus
fiat_payout.processingThe payout is sent to the payout partner.processing
fiat_payout.completedThe beneficiary's account has been credited.completed
fiat_payout.failedDelivery failed or was returned (funds refunded).failed
fiat_payout.blockedScreening blocked the beneficiary (no funds moved).blocked
json
{
  "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.

bash
curl https://api.caiboglobal.com/v1/fiat-payouts/fpo_9a8b7c6d5e4f \
  -H "X-API-Key: $CAIBO_API_KEY"

Errors

HTTPtypecodeWhen
401authentication_errorapi_key_missing / api_key_invalidNo key, or an unknown/revoked key.
403permission_errorscope_insufficientThe key lacks payouts:read.
404invalid_request_errorresource_missingNo 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

ParameterTypeDescription
limitintegerPage size, 1–100. Defaults to 25.
starting_afterstringA fiat payout id; returns the page after it. See Pagination.
statusstringFilter by a single status, e.g. completed.
countrystringFilter by destination country, ISO-3166 alpha-2.

Request

bash
curl "https://api.caiboglobal.com/v1/fiat-payouts?limit=25&status=completed" \
  -H "X-API-Key: $CAIBO_API_KEY"

Response — 200 OK

json
{
  "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

HTTPtypecodeWhen
401authentication_errorapi_key_missing / api_key_invalidNo key, or an unknown/revoked key.
403permission_errorscope_insufficientThe key lacks payouts:read.
429rate_limit_errorrate_limitedToo many requests.