API reference/Getting started
Pay anyone, anywhere, from code.
Payouts to bank accounts in 40 currencies, mobile money, wallets or a phone number. Batches with approvals, payment links, virtual accounts and signed webhooks. Generated from the OpenAPI spec; fees, limits and arrival times come back on every channel and every quote.
One USDC balance. Fund by bank transfer in USD, EUR or MXN, or on-chain. Pay out to bank accounts in 40 currencies, a mobile payment account, a wallet, or a phone number or email. A first payout is five calls: list channels, save a recipient with the fields that corridor needs, quote, send with an idempotency key, then poll or subscribe.
List channels
/channelsEvery destination with status, coverage, recipient type, limits, typical arrival and your fee at your current tier.
Response 200
{
"data": [
{
"id": "spei_mxn",
"status": "live",
"country": "MX",
"currency": "MXN",
"rail": "spei",
"recipient_type": "bank_account",
"arrival": {
"min": "PT0M",
"max": "PT5M"
},
"limits": {
"min": "30.12",
"max": "300000.00",
"currency": "USDC"
},
"fee": {
"percent": "0.35",
"flat": "0.50",
"currency": "USDC"
}
},
{
"id": "claim_link",
"status": "live",
"country": null,
"currency": "USDC",
"rail": "claim_link",
"recipient_type": "phone",
"arrival": {
"min": "PT0M",
"max": "P30D"
},
"limits": {
"min": "1.00",
"max": "50000.00",
"currency": "USDC"
},
"fee": {
"percent": "0",
"flat": "0",
"currency": "USDC"
}
}
]
}Create a recipient
/recipientsParameters
Idempotency-Keyheaderstringoptional
| Field | Type | required | Notes |
|---|---|---|---|
| type | RecipientType | required | |
| country | string | optional | |
| currency | string | optional | |
| name | string | optional | |
| kind | enum: individual, business | optional | |
| external_id | string | optional | |
| bank_account | object | optional | Fields from the channel requirements. |
| pagomovil | object | optional | |
| wallet | object | optional | |
| phone | object | optional | |
| object | optional | ||
| decaf_user | object | optional |
Request
{
"type": "bank_account",
"country": "HK",
"currency": "HKD",
"external_id": "vendor-4471",
"name": "Brightway Electronics Ltd",
"kind": "business",
"bank_account": {
"bank_name": "HSBC",
"account_number": "123456789012",
"swift": "HSBCHKHHHKH",
"id_document_number": "12345678-000-01-23-4"
}
}Response 201
{
"id": "rcp_9d1a",
"type": "bank_account",
"country": "HK",
"currency": "HKD",
"name": "Brightway Electronics Ltd",
"kind": "business",
"external_id": "vendor-4471",
"status": "ready",
"channels": [
"chats_hkd"
],
"bank_account": {
"bank_name": "HSBC",
"account_number": "•••• 9012",
"swift": "HSBCHKHHHKH"
},
"created_at": "2026-09-16T14:59:00Z"
}Errors: 422 recipient_not_ready
Create a quote
/quotesPrice one payout on one channel. Provide source_amount or destination_amount. Valid 60 seconds.
| Field | Type | required | Notes |
|---|---|---|---|
| channel | string | required | |
| source_amount | Amount | optional | Decimal string. Up to two decimals for fiat, six for USDC. |
| destination_amount | Amount | optional | Decimal string. Up to two decimals for fiat, six for USDC. |
Request
{
"channel": "chats_hkd",
"source_amount": "2500.00"
}Response 201
{
"id": "qt_5m2n",
"channel": "chats_hkd",
"source_amount": "2500.00",
"source_currency": "USDC",
"destination_amount": "19491.72",
"destination_currency": "HKD",
"rate": "7.8280",
"fees": {
"provider": "1.25",
"decaf": "8.75",
"fx_spread": "3.90",
"total": "13.90",
"currency": "USDC"
},
"arrival": {
"min": "PT1M",
"max": "P3D"
},
"expires_at": "2026-09-16T15:04:05Z"
}Errors: 400 validation_error, channel_unavailable, amount_out_of_range
Create a payout
/payoutsOne transfer to one recipient on one channel. Pass a saved recipient_id or an inline recipient. Either source_amount or destination_amount. quote_id is optional; without it the payout is priced at execution.
Parameters
Idempotency-Keyheaderstringoptional
| Field | Type | required | Notes |
|---|---|---|---|
| recipient_id | string | optional | |
| recipient | InlineRecipient | optional | |
| channel | string | required | |
| quote_id | string | optional | |
| source_amount | Amount | optional | Decimal string. Up to two decimals for fiat, six for USDC. |
| destination_amount | Amount | optional | Decimal string. Up to two decimals for fiat, six for USDC. |
| reference | string | optional | |
| memo | string | optional | Travels with the payment where the rail supports it. |
| message | string | optional | Claim links only. Shown to the recipient. |
Request
{
"recipient_id": "rcp_9d1a",
"channel": "spei_mxn",
"quote_id": "qt_5m2n",
"source_amount": "1000.00",
"reference": "INV-2026-0912",
"memo": "Freight, week 37"
}Response 201
{
"id": "po_1b7e",
"status": "submitted",
"channel": "spei_mxn",
"recipient_id": "rcp_9d1a",
"source_amount": "1000.00",
"source_currency": "USDC",
"destination_amount": "16865.35",
"destination_currency": "MXN",
"rate": "16.86535",
"fees": {
"provider": "0.50",
"decaf": "5.00",
"total": "5.50",
"currency": "USDC"
},
"reference": "INV-2026-0912",
"estimated_arrival": "2026-09-16T15:20:00Z",
"provider_reference": null,
"attempts": 1,
"created_at": "2026-09-16T15:01:12Z"
}Errors: 400 validation_error, channel_unavailable, amount_out_of_range; 402 insufficient_balance; 409 idempotency_conflict; 410 quote_expired
Examples: Create a payout
curl -X POST https://sandbox.api.decaf.so/v1/payouts \
-H "Authorization: Bearer $DECAF_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"recipient_id":"rcp_9d1a","channel":"spei_mxn","quote_id":"qt_5m2n","source_amount":"1000.00","reference":"INV-2026-0912","memo":"Freight, week 37"}'Get a payout
/payouts/{id}Includes an attempts array with timing, status and provider error per attempt.
Parameters
idpathstringrequired
Reference FAQ
Questions about the reference.
Get access
Build against the sandbox this week.
Tell us the corridors you need and the recipients you pay. Sandbox keys are issued by a person.