Skip to main content

Error envelope

Every non-2xx response shares one shape. All field names are snake_case, and the HTTP status equals status_code.
{
  "correlation_id": "abc-123",
  "code": "NOT_FOUND",
  "message": "Market not found",
  "status_code": 404,
  "timestamp": "2026-06-03T10:15:30.000Z",
  "path": "/v1/markets/0x.../book"
}
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

CodeHTTPWhen
AUTH_MISSING401Required credentials absent
AUTH_INVALID401Bad JWT, bad key, or bad secret
AUTH_REVOKED401API key revoked
FORBIDDEN403Authenticated but not allowed (e.g. missing permission)
NOT_FOUND404Market / key / chain not found
ORDER_NOT_FOUND404order_hash not owned by caller or doesn’t exist
MARKET_NOT_ACTIVE422Market is not OPEN and the endpoint needs it to be
MARKET_NOT_CLOB422Market is AMM — use the AMM routes instead
INSUFFICIENT_BALANCE422Collateral or position shortfall
ORDER_EXPIRED422Order past its expiration
ORDER_ALREADY_FILLED422Cannot cancel a fully filled order
INVALID_SIGNATURE422EIP-712 signature verification failed
WALLET_MISMATCH422Order signer ≠ authenticated wallet
PRICE_OUT_OF_RANGE422price outside [0.01, 1.00]
SIZE_TOO_SMALL422size below the minimum
BATCH_SIZE_EXCEEDED422More than 15 orders in one placement
IDEMPOTENCY_CONFLICT409Same fs-idempotency-key replayed with a different body
SERVICE_DEGRADED503Upstream (chain / DB / cache) unhealthy
INTERNAL_ERROR500Anything uncaught

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[]:
{ "error": { "code": "WALLET_MISMATCH", "message": "..." } }
Always iterate results[] and check each item. Success items have an order_hash.

Batch caps

EndpointMax
POST /v1/orders15 orders per request
POST /v1/orders/cancel (by hash)100 hashes per request
POST /v1/orders/cancel (filter / cancel-all)No fixed cap — all matching open orders
Exceeding the placement cap returns BATCH_SIZE_EXCEEDED (422). A hash list over 100 fails request validation (422).

Idempotency

Set fs-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 bodyIDEMPOTENCY_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:
{ "data": [], "next_cursor": "...", "has_more": true }
  • cursor — opaque string from the prior response’s next_cursor. A malformed cursor is treated as no cursor.
  • limit — default 20, max 100.
Results are ordered newest first (created_at descending).