Rate limits

Per-second budgets, request weights, burst behaviour, daily caps and the X-RateLimit headers.

Limits are enforced per second on a sliding window, in two kinds of bucket: an anonymous per-IP bucket for unauthenticated market data, and a per-API-key bucket for everything signed. Your VIP tier sets the numbers; market makers get raised limits.

Budgets

Values below are tier 0 — the floor every new key starts at, and the fallback the gateway applies if the tier table is briefly unreadable.

BucketTier-0 limitBurst (×1.5)
Read (GET)50 /s75
Order placement10 /s15
Cancel20 /s30
Modify10 /s15
Batch3 /s4
Advanced orders5 /s7
WebSocket messages50 /s75
CeilingTier 0
WebSocket connections3
WebSocket subscriptions50
Requests per day50,000
Orders per day1,000

The window is one second. The burst multiplier is applied to the base limit and the burst number is what is actually enforced — it is also what the X-RateLimit-* headers report, so headers and enforcement never disagree.

Weights

Requests cost more than one slot when they do more than one thing:

ClassWeight
Read, order, cancel, modify1
Advanced order (TWAP, VWAP, bracket, …)2
Batch (multi-order place, batch cancel, position sweeps)3

So a tier-0 key gets ~15 order placements per second, but only one batch call per second-window (weight 3 against a burst budget of 4). Sizing a batch to 20 legs is the intended use — spraying 20 single orders costs the same budget and more latency.

Headers

Every response carries the state of the bucket it was charged to:

x-ratelimit-limit: 75        # enforced burst limit for this bucket
x-ratelimit-remaining: 74    # slots left in the current window
x-ratelimit-reset: 1790094907  # unix seconds when the window rolls
x-ratelimit-used: 1          # weight consumed so far in this window

Drive your pacing off remaining rather than counting locally — the same key shares buckets across every process using it.

Rejections

CodeNumHTTPMeaning
RATE_LIMIT_IP19001429anonymous per-IP bucket exhausted
RATE_LIMIT_KEY19002429per-key general bucket exhausted
RATE_LIMIT_ORDER19003429order-placement bucket exhausted
RATE_LIMIT_CANCEL19004429cancel bucket exhausted
RATE_LIMIT_WS19010429WebSocket message rate, connection or subscription ceiling
RATE_LIMIT_FAUCET19005429testnet faucet cooldown

A daily cap is a different failure: it returns 403, not 429, and no amount of backoff clears it before the UTC day rolls.

Practical pacing

  • Back off on the bucket that rejected you, not globally — a 429 on orders says nothing about your read budget.
  • Prefer one WebSocket subscription over polling a ticker; the 50 /s read budget disappears fast across a handful of markets, and the socket is fresher.
  • Cancels are cheaper than placements by design (20 /s vs 10 /s at tier 0). Cancel-replace loops should not need a raised tier.
  • If you are systematically hitting ceilings at tier 0, the fix is a tier change (VIP level or market-maker flag), not more retries. GET /api/v1/system/info reports the limits your key is actually running under.

Did this page help you?