1. Find the method
Every destination is addressed by a method code from the capabilities catalog —gh_mtn, ng_gtbank, ke_mpesa. The catalog also tells you what fields the method needs, its limits, and how long it settles.
2. Validate the destination
Resolve the account holder before you send. It’s free on sandbox, cheap on production, and catches the transposed digit that would otherwise pay a stranger.POST /v1/validate/bulk takes up to 100.
3. Send
201 returns the payout in pending; 200 means this externalReference was already used and you’re seeing the original — see Idempotency.
Which side carries the amount
Exactly one ofto.amount or from.amount:
to.amount— “deliver exactly this much.” The most common case. Your balance is debited whatever that costs.from.amount+from.currency— “debit exactly this much from this balance.” Use it for cross-currency payouts:from: { amount: 100, currency: "USD" }to a GHS destination converts at the live rate and delivers the result.
Saved recipients
If you pay the same destination repeatedly, create it once withPOST /v1/recipients — validation happens at creation and the holder name is stored. Then reference it by its details as above; the API matches it to the saved recipient.
Crypto destinations
Useto.address instead of to.accountNumber, and to.tag for chains that need a memo (Stellar, Ripple). The asset and chain come from the method code (e.g. usdc_solana). Amounts are in the asset; cross-currency from a fiat balance is priced at the live rate.
4. Confirm
Subscribe topayout.completed and payout.failed. A failed payout carries statusMessage and has already refunded your balance — nothing to unwind. For a one-off check, GET /v1/payouts/{id} includes attempts (each provider try) and timeline (the full audit trail).
Things that bite
- Zero-decimal currencies (UGX, TZS, RWF) reject fractional amounts.
- Each method has
limits.min/limits.max; your organization may also have daily/monthly caps (payout_limit_exceeded). - On sandbox the amount’s cents choose the outcome —
150.07goes pending and then fails. See Sandbox. - KYC objects (
from.kyc,to.kyc) are accepted and echoed back; requirements vary by corridor — we’ll tell you if a specific corridor needs them.