Errors
Full error code table — numeric code, HTTP status, and when each fires.
One shape for every error: { "code": <number>, "msg": "<CONSTANT>" }. The numeric codeis the contract — switch on it once and you’ve handled every failure below. The HTTP status is a hint, not a rule.
| code | msg | HTTP | Description |
|---|---|---|---|
| 0 | — | 200 | Success. |
| 1 | INVALID_REQUEST | 400 | Body fails validation: unsupported asset, disabled pair, unparseable amount, invalid address, FLOAT without refundAddress, malformed Idempotency-Key. The same code + HTTP 409 fires on Idempotency-Key reuse with a different payload. |
| 2 | AUTH_REQUIRED | 401 | One of X-API-KEY / X-API-SIGN is missing on an endpoint that requires authentication. |
| 3 | AUTH_INVALID | 401 | Unknown key, malformed signature, signature mismatch, expired or replayed nonce, decrypt failure. Generic body — never an oracle for "which" of those it was. |
| 4 | AUTH_DISABLED | 401 | Partner record enabled = false. Reachable only with a valid signature, so the operator can distinguish a kill-switched partner from a stolen-and-revoked key. |
| 5 | RATE_LIMIT | 429 | Per-partner weight budget exhausted within the 60-second sliding window. Response includes Retry-After: <seconds>. |
| 6 | NOT_FOUND | 404 | Order does not exist OR exists but belongs to a different partner OR exists and the token is wrong. The three cases collapse to one envelope. |
| 7 | LIMIT_MIN | 400 | Create amount below the per-pair USD minimum. /v1/price returns from.min / to.min for pre-validation but does not itself emit this code. |
| 8 | LIMIT_MAX | 400 | Create amount above the per-pair USD maximum or the operator daily cap. /v1/price returns from.max / to.max for pre-validation but does not itself emit this code. |
| 9 | RESERVE_EXCEEDED | 503 | Reserved for a future per-partner capacity control. No current route emits this code — partners can safely omit it from exhaustive handlers until announced. |
| 10 | MAINTENANCE | 503 | The site is in operator-toggled upgrade mode. Retry after a short delay. |
| 11 | UPSTREAM_ERROR | 503 | A required upstream is temporarily unavailable. Retry with exponential backoff. |
| 12 | EMERGENCY_INVALID_CHOICE | 400 | POST /v1/emergency body has `choice` other than `EXCHANGE`. |
| 13 | LIMIT_EXCEEDED | 403 | Partner reached the per-partner ceiling on POST /v1/codes (default 50 reference codes). |
| 14 | ROTATION_CONFLICT | 409 | Concurrent POST /v1/keys/rotate lost the conditional-claim race. The other call already rotated the secrets; treat the rotation as done and use whichever new secret was returned to that caller. If the new secret was not captured, request a fresh rotation through the operator. |
| 99 | INTERNAL | 500 | Unexpected server-side condition. Already logged on our side; safe to retry. |
A few codes (AUTH_INVALID, AUTH_DISABLED, NOT_FOUND) cover multiple internal conditions on purpose. Finer discrimination is not part of the contract; one switch on code in your client is enough.
See also: Errors cookbook for per-code remedies (symptom, cause, fix).