Rate limits
A flat per-key request limit, meant to absorb accidental request storms rather than to meter normal usage.
The limit
| Scope | Limit |
|---|---|
| Per API key | 60 requests per minute |
The limit is applied per key, not per workspace, so two keys in the same workspace each get their own 60-per-minute allowance rather than sharing one pool. It's a request-count limit, not a token-count limit: a single request that generates a very long response counts the same as one that generates a very short one, and streaming vs. non-streaming makes no difference to how a request is counted.
This limit exists primarily as a safeguard against runaway loops, a retry loop with no backoff, a bug that fires a request per keystroke, rather than as a meaningful ceiling on legitimate usage. Ordinary application traffic, even fairly active chat usage, sits well under it.
Going over the limit
A request that exceeds the limit gets a 429 immediately, without being queued or delayed, in the same error envelope as any other error:
HTTP/1.1 429 Too Many Requests
{"error": {"message": "Rate limit exceeded. Please slow down and retry.", "type": "rate_limit_error"}}
The window resets on a rolling basis, so the right response to a 429 is a short pause before retrying, not switching to a different key or assuming something is broken. A single 429 in the middle of a burst of activity is normal and expected; repeated 429s across many separate bursts are a sign the request pattern itself needs a backoff strategy, covered below.
Backing off correctly
Retrying a 429 immediately, in a tight loop, makes the situation worse, not better: it keeps the request rate exactly where it was over the limit, so every retry fails the same way. A short, ideally increasing delay between attempts (a few hundred milliseconds, doubling on each consecutive failure, up to a sensible cap) resolves almost every 429 within one or two retries without meaningfully affecting the user-visible latency of a normal request.
# Python: minimal retry with exponential backoff import time for attempt in range(4): try: response = client.chat.completions.create(model="tai-4.1", messages=messages) break except Exception as e: if attempt == 3: raise time.sleep(0.5 * (2 ** attempt))
The official OpenAI SDKs already implement retry-with-backoff behavior for exactly this kind of transient error by default; if you're using one of them, this is likely already handled for you without any extra code, and you'll only see a raised exception after its own retry budget is exhausted.
If 60 per minute is genuinely too low
For most applications, request volume is naturally bounded by how quickly a human or an agent loop can actually generate requests, and 60 per minute is rarely a real constraint. If a legitimate use case is consistently hitting the limit, the first thing worth checking is whether requests can be batched or consolidated, sending fewer, larger requests rather than many small ones for the same underlying task, before assuming the limit itself needs to change.