Core concepts

Payouts

Payouts move merchant balance out to destinations you control. Use destination availability and idempotency for safe execution.

Create payout

POST/v1/payoutsCreate payout request
FieldTypeDescription
assetrequiredstringSettlement token, or token:chain. Chain must match the operator-configured treasury withdrawal rail for that token (see GET /v1/payouts/withdrawal-rail).
amountrequiredstringAmount in base units for selected asset.
railrequiredstringDestination rail (for example crypto or fiat).
destination_addressstringDestination wallet/account detail when required.
totp_codestringConsole only (user JWT): payout authenticator code. Not used with API key auth.
email_otp_codestringConsole only: email OTP when enabled.
curl "$XPEND_BASE_URL/v1/payouts" \
  -H "Authorization: Bearer $XPEND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: payout_req_4021" \
  -d '{
    "asset": "usdc:ethereum",
    "amount": "125000000",
    "rail": "crypto",
    "destination_address": "0x1234..."
  }'

Check availability first

GET/v1/payouts/withdrawal-railCanonical chain + withdrawal gates per token
GET/v1/payouts/destination-availabilityOperator-enabled payout networks
GET/v1/payouts/fiat-availabilityOperator-enabled fiat corridors

Balance reservation

Creating a payout reserves the payout amount from available_balance into reserved_balance until the withdrawal completes or is cancelled. Spendable balance for new payouts is available_balance only. A fixed USDT processing fee may apply on withdrawal (ledger debit only — no on-chain fee transfer).

Operator-enabled withdrawal rails only

Payout create is rejected unless the settlement chain is enabled for withdrawals in your environment. For crypto, operators configure the canonical treasury chain per token (TreasuryLiquidityPolicy) and which destination networks accept payouts (PlatformPayoutEnabledChain allowlist and blocks). Merchants cannot pick an arbitrary chain — call GET /v1/payouts/withdrawal-rail?token=usdc and GET /v1/payouts/destination-availability before building payout UI or automation. Fiat bank withdrawals must use a corridor from GET /v1/payouts/fiat-availability.

For crypto, combine withdrawal rail (per-token canonical chain and treasury gates) with destination availability (platform-enabled networks). For fiat, use fiat availability and optionally institutions / beneficiary resolve before create.

Fiat bank payout

POST/v1/payouts/fiat/institutionsList banks for a corridor
POST/v1/payouts/fiat/beneficiary/resolveResolve account name
curl "$XPEND_BASE_URL/v1/payouts" \
  -H "Authorization: Bearer $XPEND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: payout_fiat_4021" \
  -d '{
    "rail": "fiat",
    "asset": "usdc:ethereum",
    "amount": "2000000",
    "fiat": {
      "method": "BANK_TRANSFER",
      "bank_code": "058",
      "account_number": "0123456789",
      "receive_currency": "NGN"
    }
  }'

Fiat beneficiary fields

For local bank payouts, send fiat.bank_code and fiat.account_number plus receive_currency. The platform resolves the account holder name (and bank label when available) automatically — you do not need beneficiary_name or bank_name unless you want to supply them explicitly. Use POST /v1/payouts/fiat/beneficiary/resolve to preview resolution before create.

Read and cancel

GET/v1/payoutsList payouts
GET/v1/payouts/{id}Get payout status/details
POST/v1/payouts/{id}/cancelCancel payout if still cancellable

Operational model

  • Create payout once with a stable idempotency key.
  • Persist payout ID and show status to operators.
  • Consume webhook events for status transitions.
  • Allow cancel only while payout is not terminal/executed.

Security posture

Payouts authenticated with an API key do not require totp_code — the key itself is the automation credential. Merchant console (user JWT) withdrawals still require step-up verification via payout authenticator or email OTP. See /business/docs/security.

See endpoint-level details in /business/reference/payouts.