Skip to main content
OCX uses standard HTTP status codes with a consistent JSON error body. Always branch on the status code first, then read error/message for detail.

Error shape

{
  "error": "INSUFFICIENT_MARGIN",
  "message": "Order requires 512.00 USDC margin; 210.00 available"
}
error is a stable, machine-readable code you can switch on; message is a human-readable explanation that may include specifics (amounts, the bucket to transfer from). New codes may be added over time — treat an unrecognized code as a generic failure of its status class.

Status codes

StatusMeaningWhat to do
200 / 201SuccessRead the response body.
400Bad request — malformed body, invalid enum, or insufficient bucket balanceFix the request; don’t retry unchanged.
401Not authenticated — missing/expired session or keyRe-run the SIWE flow or check your x-api-key.
403Forbidden — wrong scope, IP not allowed, or action not permittedUse a trade-scoped key; check IP allowlist.
404Unknown resource — market, order, or record not foundVerify the id.
409Conflict — duplicate clientOrderId or conflicting stateTreat as already-applied; reconcile.
422Business rejection — the request was valid but the engine declined itHandle by code (see below); do not blindly retry.
429Rate limitedBack off until the window resets.
5xxServer or upstream errorRetry with backoff; if persistent, contact support.

Common business rejections

These come back on trading and wallet endpoints. They are expected outcomes, not bugs — handle each deliberately.
The order would breach your available margin. Every order passes a server-side margin gate before acceptance. Read your headroom from GET /perps/positions and GET /perps/balances, reduce size, or fund the venue — do not retry the same order.
A transfer or withdrawal exceeds the source bucket’s available balance. Withdrawals draw only from wallet; transfer back from perps/options/spot first. Returned as 400.
A postOnly order would have taken liquidity, so it was rejected to keep you on the maker side. Re-price behind the touch and resubmit.
A reduceOnly order would have increased your position (e.g. wrong side or already flat). Check your current position before retrying.
A multi-leg combo could not fill every leg immediately. Combos are all-or-none (FOK) — the whole strategy is rejected and nothing executes. Re-price the legs and resubmit.
An ioc order found no liquidity to take, or a fok order could not be filled in full. Nothing rests; adjust price or time-in-force.
A 422 business rejection is not a transport failure. Retrying it unchanged will fail the same way and can burn your rate budget — fix the cause first.

Rate limits

Requests are rate-limited per client. Authenticated sessions and API keys get a higher budget than anonymous traffic. Every response carries the current window state so you can pace yourself.
HeaderMeaning
X-RateLimit-LimitRequests allowed in the current window
X-RateLimit-RemainingRequests left in the window
X-RateLimit-ResetWhen the window resets
When you exceed the budget you receive 429 Too Many Requests. Back off until X-RateLimit-Reset, ideally with exponential backoff and jitter.
Do not tight-poll market data. Prefer the streaming endpoints for live books, marks, fills, and balances — one long-lived SSE connection replaces thousands of polling requests and keeps you well under any limit.

Handling 429 in practice

async function call(url, opts, attempt = 0) {
  const res = await fetch(url, opts);
  if (res.status === 429 && attempt < 5) {
    const reset = Number(res.headers.get("X-RateLimit-Reset")) || 0;
    const waitMs = Math.max(reset - Date.now(), 250 * 2 ** attempt);
    await new Promise(r => setTimeout(r, waitMs));
    return call(url, opts, attempt + 1);
  }
  return res;
}

Idempotency

To make retries safe, send a clientOrderId on order and quote endpoints. If a response is lost and you retry, the same clientOrderId prevents a duplicate order — reconcile by reading the resulting order rather than assuming it failed. Quoting endpoints also accept a quoteId to group and atomically replace a market-maker’s quote set.