Error codes
Every error response is JSON with a stable machine-readable error code.
Branch on the code, never on the human-readable text.
| Code | HTTP status | Meaning |
|---|---|---|
invalid_request | 400 | The request body or parameters failed validation. |
idempotency_key_required | 400 | A money-moving request was sent without an Idempotency-Key header. |
unsupported_grant_type | 400 | The grant_type was not client_credentials (only client-credentials grants are supported). |
client_certificate_required | 401 | No mTLS client certificate was presented on the connection. |
invalid_client | 401 | The client_id/client_secret pair is unknown, revoked, or wrong for this environment. |
invalid_token | 401 | The bearer token is missing, expired, malformed, or not bound to the presented certificate. |
invalid_signature | 401 | The detached JWS signature does not verify against your registered signing key. |
stale_timestamp | 401 | The X-Timestamp header is outside the ±300-second acceptance window. |
replayed_nonce | 401 | The X-Nonce value has already been used by this client. |
signing_key_not_registered | 401 | No ES256 signing public key is registered for this client. |
ip_not_allowed | 403 | The request originated from an IP address outside your registered allowlist. |
quote_not_found | 404 | The referenced quote_id does not exist for this partner. |
order_not_found | 404 | The referenced order does not exist for this partner. |
withdrawal_not_found | 404 | The referenced withdrawal does not exist for this partner. |
account_not_provisioned | 404 | No funding account has been provisioned for this partner yet. |
quote_already_used | 409 | The quote has already been executed by a previous order. |
quote_expired | 409 | The 60-second quote validity window has passed; request a new quote. |
insufficient_funds | 409 | The SAR balance is too low to cover the buy order or withdrawal. |
insufficient_gold | 409 | The gold holdings are too low to cover the sell order. |
idempotency_key_conflict | 409 | The Idempotency-Key was already used with different request parameters. |
settlement_iban_not_configured | 409 | No settlement IBAN is registered, so withdrawals cannot be requested. |
rate_limited | 429 | You exceeded your per-minute rate limit; retry after the Retry-After header. |
execution_failed | 502 | Order execution failed downstream; the order is recorded as failed and embedded in the response, and an order.failed webhook is sent. |
price_unavailable | 503 | No fresh gold price is available right now; retry shortly. |