Error envelope
request_id— include this when contacting supporterror.code— machine-readable; safe to switch onerror.message— human-readable; do not parse
HTTP status codes
| Status | Meaning | Typical codes |
|---|---|---|
200 / 201 | Success | — |
400 | Bad request — fix the request and retry | validation_error, bad_request |
401 | Authentication failed | unauthorized, invalid_signature, jwt_expired |
403 | Authenticated but not allowed | forbidden, ip_not_allowed, account_suspended |
404 | Resource not found | not_found, quote_not_found |
409 | State conflict | quote_used, wallet_frozen |
413 | Request body too large (>64 KB) | bad_request |
422 | Business rule rejection — retry will not help | see below |
429 | Rate limit hit; wait and retry | rate_limited |
500 | Our problem; safe to retry with backoff | internal_error |
422 — business rule codes
These represent rules the request violated, not syntax errors.| Code | Trigger |
|---|---|
insufficient_funds | Wallet balance is too low to cover the transaction amount |
per_payout_limit_exceeded | Transaction exceeds your per-transaction cap |
daily_limit_exceeded | Today’s send volume would exceed your daily cap |
monthly_limit_exceeded | This month’s send volume would exceed your monthly cap |
quote_expired | The quote has expired |
invalid_signature | Quote signature mismatch |
rate_moved | Exchange rate moved more than 0.5% since the quote was issued |
screening_failed | Recipient failed sanctions screening |
Retrying
| Status | Retry? |
|---|---|
5xx, 429 | Yes, with exponential backoff (start at 1s, max 60s) |
401 jwt_expired | Re-login and retry once |
All other 4xx | No — fix the request first |
idempotency_key on sendPayoutRequest so a retry after a network error does not accidentally create a duplicate transaction.