error.code, never on the message text.
Error envelope
code— stable identifier from the table below. New codes may be added; treat unknown codes on a5xxas retryable and unknown codes on a4xxas terminal.message— human-readable detail. Log it, don’t parse it.request_id— attach this to any support ticket so the team can trace the exact request.
Error codes
Both
INSUFFICIENT_CREDIT and AML_DECLINED return 402 Payment Required — always branch on the code, not the status. One is recoverable by the operator; the other is a compliance decision.Retry strategy
Not every error deserves a retry. Classify by code: Retryable — back off exponentially (e.g. 1s, 2s, 4s, 8s, capped), reusing the sameIdempotency-Key on POSTs so a retry can never double-execute:
RATE_LIMITED— but honor theRetry-Afterheader instead of your own schedule.INTERNAL— and any other5xx, plus network timeouts.
INSUFFICIENT_CREDIT— raise limits or add collateral.AGENT_NOT_ALLOWLISTED— allowlist the agent.WITHDRAWAL_GATED,OUTSTANDING_BALANCE— clear the outstanding credit.ORDER_EXPIRED— create a new order (a neword_ID, so a new idempotency key too).
INVALID_API_KEY,INVALID_AGENT— configuration bugs; fix your setup.AML_DECLINED,AGENT_REVOKED— compliance or lifecycle decisions; retrying just burns rate limit.
Next steps
Error Handling Guide
Decline and retry patterns inside the payment flow.
Troubleshooting
Step-by-step fixes for the most common failures.
Webhook Events
Failure events like payment.failed and agent.aml_declined.

