success: false and an error object. Branch your logic on the stable error.code — never on the HTTP status alone or the human-readable message (which may change).
Stable machine-readable identifier. Match on this.
Human-readable description. For logs and debugging; do not parse.
Optional context. Present on some errors (e.g. the conflicting
external_id, or the field map on validation errors).Validation errors
A malformed request body or query returns422 VALIDATION_ERROR with details as a map of field → [messages]:
Authentication & account
Returned on any endpoint.Invoices
POST /external/invoices, GET /external/invoices, GET /external/invoices/{ident}.
INVOICE_ALREADY_EXISTS is idempotency working as intended — the details carry the existing invoice’s status, so you can reconcile without creating a duplicate.Webhooks
GET /external/invoices/{ident}/webhooks, POST /external/invoices/{ident}/resend-webhook.
Withdrawals
GET /external/withdrawals, GET /external/withdrawals/{withdrawal_uuid}.
Rates
GET /external/rates.
Rate limiting
Returned on any endpoint when limits are exceeded.Server-side
Handling strategy
Client error — fix the request. Do not blind-retry; the same call fails again.
Back off and retry with exponential backoff.
Transient — retry idempotent calls with backoff. Invoice creation is safe to retry thanks to
external_id idempotency..webp?fit=max&auto=format&n=O6SgNi-K863CxPv7&q=85&s=5a022604a7f294c9858b55256ba8a593)
