Error responses

The error envelope, the full code families, and which failures are safe to retry.

Failures use the same envelope as successes, with success: false and an error object:

{
  "success": false,
  "error": {
    "code": "TRADE_INSUFFICIENT_MARGIN",
    "codeNum": 13002,
    "message": "Insufficient margin",
    "details": { "required": "142.50", "available": "98.11" }
  },
  "meta": { "requestId": "req_b2fbe365c9604884a4d202b451c57e45", "timestamp": 1790094673430 }
}

code is the stable identifier. codeNum is the same thing as a 5-digit integer for clients that prefer numeric switches. message is human-facing and may be reworded at any time — never match on it. details is present when there is structured context worth acting on (which market, how much was missing) and absent otherwise.

Families

The first two digits tell you which subsystem refused, which is usually enough to decide whether to fix the request, fix the account, or retry.

RangeFamilyMeaning
100xxREQ_*malformed request — bad JSON, missing field, invalid market/side/price/size/TIF
1005xRESOURCE_*generic not-found / already-exists
110xxAUTH_*credential, signature, timestamp, replay
111xxPERM_*key lacks the right, IP not allowed, account blocked
120xxACCT_*account state — suspended, KYC, withdrawal locks
130xxTRADE_*admission control — margin, size, price band, market state, slippage
131xxORDER_*order lifecycle — not found, already filled/cancelled, duplicate client id
140xxPOS_*position state — not found, already closed, TP/SL conflicts
150xxbridge, withdraw, transfer, fund, championship, payment, on-ramp, strategy
170xxPRED_*prediction markets
180xxADV_*advanced orders — duration, interval, trigger price, already triggered
190xxRATE_LIMIT_*see Rate limits
250xxrisk engine — leverage, margin, liquidation phase, reduce-only, IOC no-fill
415xxportfolio risk — deficit risk, warning zone
500xxSYS_*internal, maintenance, overload, timeout, DB, chain, global halt

The ones you will actually hit

CodeNumWhat it means in practice
REQ_INVALID_PARAMS10001a value failed validation; details names the field
AUTH_INVALID_SIGNATURE11003canonical payload built wrong — see Authentication
AUTH_TIMESTAMP_EXPIRED11004host clock more than 30 s off
AUTH_REPLAY_DETECTED11013identical signature resent; re-sign with a fresh timestamp
PERM_NO_TRADING11101read-only key
TRADE_INSUFFICIENT_MARGIN13002order needs more margin than the account has free
TRADE_SIZE_TOO_SMALL13003below the market's minimum size or notional
TRADE_PRICE_DEVIATION13005limit price outside the venue price band around mark
TRADE_MARKET_CLOSED13006session-bound market (equities, options on equities) outside hours
TRADE_POST_ONLY_FAIL13009post-only order would have taken
TRADE_SLIPPAGE_EXCEEDED13016fill would have been worse than your slippage / maxSlippageBps bound
TRADE_MARKET_NOT_FOUND13014symbol does not exist — check spelling against /system/info
ORDER_DUPLICATE_CLIENT_ID13106clientOrderId already used; the first order stands
POS_TPSL_EXISTS14005position already protected; resend with replace: true to take over
SYS_OVERLOAD / SYS_TIMEOUT50003 / 50004transient — retry with backoff
SYS_MAINTENANCE / SYS_GLOBAL_HALT50002 / 50009trading is stopped platform-wide; do not retry in a loop

Retry rules

  • Safe to retry with backoff: 50003, 50004, 50005, 50007, 13015 (concurrency conflict), 13018 (engine not ready yet).
  • Never retry blindly on order placement. A network timeout does not tell you whether the order reached the book. Always send a clientOrderId, then either retry with the same id (the exchange rejects the duplicate rather than double-filling) or reconcile with GET /api/v1/perp/orders.
  • Do not retry 110xx, 111xx, 100xx or 13001–13014 unmodified — the request or the account state has to change first.
  • Log meta.requestId on every non-2xx. It is the only handle that resolves to the exact server-side log line.

Did this page help you?