Error envelope
Every non-2xx response shares one shape. All field names are snake_case, and the HTTP status equalsstatus_code.
correlation_id comes from the request’s correlation id or the
x-correlation-id header; it falls back to "unknown". Quote it when reporting
an issue.
Error codes
Inline vs HTTP errors
POST /v1/orders splits errors two ways:
- Request-level failures (batch size, auth) are HTTP errors.
- Per-order rejections (wallet mismatch, bad signature, market closed) are
returned inline inside
results[]:
results[] and check each item. Success items have an
order_hash.
Batch caps
Exceeding the placement cap returns
BATCH_SIZE_EXCEEDED (422). A hash list over
100 fails request validation (422).
Idempotency
Setfs-idempotency-key: <string> on POST /v1/orders:
- Keyed per
(user, key), with the request body hash stored alongside the result. - Same key + same body → returns the cached result with
_idempotent_replayed: true. - Same key + different body →
IDEMPOTENCY_CONFLICT(409). - Honored on order placement only.
Pagination
All list endpoints (/v1/markets, /v1/orders, /v1/fills, /v1/positions,
/v1/markets/{id}/trades) share a cursor envelope:
cursor— opaque string from the prior response’snext_cursor. A malformed cursor is treated as no cursor.limit— default20, max100.
created_at descending).