Rate Limits
The API enforces rate limits at multiple layers. If you're seeing 429 Too Many Requests, this is the page.
| Scope | Behavior |
|---|---|
| Per IP (all requests) | 10 req/s sustained, burst of 20 — applies before auth |
| Per authenticated user | 20 req/s sustained, burst of 40 |
| Per API key | Token bucket with a per-key limit (default 5 req/s) |
| Failed auth attempts | Repeated failures from one IP trigger a temporary block |
| WebSocket messages | 10 msg/s per connection, burst of 20 |
| WebSocket connections | Max 5 per user (excess: close code 4008, or HTTP 429 on header-auth) |
When rate-limited, the server returns 429 with an error field naming the
limit that fired: rate_limit_exceeded (per-IP or per-user),
api_key_rate_limited (per-key), or too_many_failed_attempts (auth-failure
block). A Retry-After header indicates when to retry.
Practical guidance
- For high-frequency reads (e.g. polling trade status), keep request cadence to a few per second. The rate limit is designed for normal integration patterns, not high-frequency hammering.
- Subscribe via WebSocket instead of polling where possible. The WS event stream pushes updates as they happen with no per-request rate cost.
- For burst writes (create/cancel), the token bucket gives you a short burst followed by a steady-state ceiling. Don't try to slam dozens of writes in a single second.
Failed-auth blocking
Repeated failed authentication attempts from a single IP trigger a temporary
block — requests from that IP receive 429 too_many_failed_attempts with
Retry-After: 900 (15 minutes) until it expires.
If you're running bots in a shared NAT/proxy environment (corporate network, cloud function with shared egress), one misconfigured client can trigger the failed-auth block for everyone behind that IP. Fix failing credentials promptly rather than letting a bot retry them in a loop.