Conventions
Rate limits
Per-key request quotas and how to back off
Rate limit100 requests per 60s
API key requests are limited to 100 requests per 60-second window, per key.
Session-authenticated requests share the same per-session quota. The defaults
are configurable via the API_RATE_LIMIT_MAX_REQUESTS and
API_RATE_LIMIT_WINDOW_MS environment variables on the server.
Response headers
Every authenticated response includes:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1714521600| Header | Description |
|---|---|
X-RateLimit-Limit | Total requests allowed in the current window. |
X-RateLimit-Remaining | Requests left before the limit kicks in. |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets. |
When you exceed the limit
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1714521660{
"error": "Rate limit exceeded",
"retryAfter": 42
}retryAfter is the number of seconds to wait before the next request.
Backoff strategy
- Honour
retryAfterwhen present — it's authoritative. - Otherwise compute wait from
X-RateLimit-Reset - now(). - On repeated
429s, back off exponentially with jitter to avoid thundering-herd retries.
async function withRetry(fn, attempt = 0) {
const res = await fn();
if (res.status !== 429 || attempt >= 5) return res;
const wait = Number(res.headers.get("x-ratelimit-reset")) * 1000 - Date.now();
const jitter = Math.random() * 500;
await new Promise((r) => setTimeout(r, Math.max(wait, 1000) + jitter));
return withRetry(fn, attempt + 1);
}Rate limits are per API key. Splitting traffic across multiple keys does raise the effective ceiling — but consider whether your workload should be rearchitected (caching, batching) before issuing more keys.