Rate limits
Per-key and per-IP request budgets, and the headers that report them.
Limits are enforced at two levels. Both return 429 rate_limited with a Retry-After
header and the standard RateLimit-* headers.
Per API key
Each key has a request budget per minute (default 60). When exceeded, the response
is 429 rate_limited with:
Retry-After: <seconds>RateLimit-LimitRateLimit-RemainingRateLimit-Reset
Per client IP (pre-authentication)
All requests from a client IP are subject to a coarse cap (default 300/min), applied
before authentication. A separate, stricter cap on failed-auth attempts (default
20/min) is charged whenever key resolution fails. Both return the same
429 rate_limited envelope with Retry-After and RateLimit-* headers.
Because the failed-auth cap is charged on every rejected key, it throttles credential guessing even when no valid key is ever presented.
Handling 429
Respect Retry-After; it is the number of seconds to wait before retrying. A simple,
correct client backs off for exactly that long:
async function requestWithBackoff(url, init) {
for (;;) {
const res = await fetch(url, init);
if (res.status !== 429) return res;
const wait = Number(res.headers.get("Retry-After") ?? 1);
await new Promise((r) => setTimeout(r, wait * 1000));
}
}Combine backoff with idempotency keys on writes: a retried
POST after a 429 then cannot create a duplicate.