Success envelope
Every successful response is wrapped in a data object:
The shape inside data varies by endpoint (array, keyed object, single resource, or null) — see
Groups & proposals → Response envelopes.
Error envelope
Every error returns a standard HTTP status code and a single, consistent JSON body:
message may occasionally be an array of validation strings — write your handler to accept either a
string or a string array.
Status codes
Retry semantics
retryable means “safe to resend the identical request — no funds moved and no order was
submitted.” It is not a synonym for “transient.”
retryable: true — failures where nothing stuck: RATE_LIMITED, ROUTE_NOT_FOUND,
NO_MARKET_PRICE, NO_LIQUIDITY, ORDER_NOT_FILLED, FUNDING_REFUNDED, REQUEST_IN_PROGRESS,
SLIPPAGE_EXCEEDED, UPSTREAM_TIMEOUT, UPSTREAM_UNAVAILABLE. Retry with exponential backoff
(honor Retry-After when present).
retryable: false — terminal. Fix the request; do not loop. In particular, after a write that may
have been submitted, reconcile via /positions or /trades rather than retrying — a retry can
double-submit (idempotency keys are coming in a future release).
Codes worth handling
The full machine-readable catalog (every code → status and retryable) is published as
error-catalog.json, generated from the API’s error registry. The most
common:
Handling pattern
Branch on code, back off when retryable is true (honoring Retry-After), and treat
retryable: false as terminal. For writes, reconcile via /positions or /trades instead of
blind retries.