Docs
API Reference

Rate Limits

The enforced rate-limit layers, client-visible headers, and 429 handling guidance

The API enforces several limits in sequence. Each can return 429. This page lists them and how to back off.

Enforced layers

LayerDefaultOn exceed
Per IP20 requests/second, burst 40429
Per-key RPM20 requests/minute, sliding 60s window429 with Retry-After: 60
Per-key concurrency5 in-flight requests429 Concurrent request limit exceeded with Retry-After: 5
Agent slots2 slots403 at 0 slots, 429 over the limit
BudgetEUR 50 monthly budget (api keys)429 with X-Budget-Remaining: 0
Context cap800000 characters (about 200k tokens)413

The per-key RPM, concurrency, slot, and budget figures are the current defaults. To raise them, see Account limits.

Client-visible headers

Every /v1/* response carries the rate-limit headers. Retry-After is added on 429 and 503.

HeaderMeaning
X-RateLimit-LimitConcurrent-request limit (see note below)
X-RateLimit-RemainingRemaining capacity
X-RateLimit-ResetWhen the window resets
Retry-AfterSeconds to wait before retrying

X-RateLimit-Limit currently reflects the concurrent-request limit, not requests per minute. Do not read it as RPM.

Handling 429

When you receive a 429:

  1. If Retry-After is present, wait that many seconds, then retry.
  2. Otherwise back off exponentially with jitter.

Do not retry 400, 401, 403, or 422. Those are client errors and a retry will fail the same way. See Errors for the status table.

Example backoff

import time, random

def call_with_retry(do_request, max_attempts=5):
    for attempt in range(max_attempts):
        resp = do_request()
        if resp.status_code != 429:
            return resp
        retry_after = resp.headers.get("Retry-After")
        if retry_after is not None:
            time.sleep(float(retry_after))
        else:
            time.sleep((2 ** attempt) + random.random())
    return resp

Next