Skip to Content
Rate Limits & Errors

Rate Limits & Errors

Rate limits

Limits are enforced per API key over a 60-second sliding window — not per calendar minute, so a burst does not reset at the top of the minute.

LimitDefault per key
Requests per minute60
Tokens per minute100,000

Two windows are checked independently:

  • Requests per minute — counted when the request arrives.
  • Tokens per minute — a request’s cost is unknown until it finishes, so the window is checked before the call and credited afterwards with the total from usage. A few large completions can therefore throttle the following minute.

Need different limits? Ask an administrator — they are per-key columns, adjustable without new keys.

When you are limited

429 with a Retry-After header, in seconds, derived from when the oldest request in the window expires:

HTTP/1.1 429 Too Many Requests Retry-After: 42 Content-Type: application/json
{ "error": { "message": "Rate limit exceeded: 60 requests per minute.", "type": "rate_limit_error", "code": "rate_limit_exceeded", "param": null } }

The message states which limit you hit — requests or tokens.

X-RateLimit-Remaining-style headers are not sent yet. Use Retry-After on 429, and track your own consumption from the usage field in each response.

Error format

Every error — including the gateway’s own auth and rate-limit rejections — uses the OpenAI envelope, so SDK error handling works unchanged:

{ "error": { "message": "Human-readable description.", "type": "invalid_request_error", "code": "invalid_api_key", "param": null } }

code is null for request-validation failures; param names the offending field when the gateway can identify it.

Every error code

StatustypecodeCause
400invalid_request_errornullValidation failed; param names the field
401invalid_request_errormissing_api_keyNo Authorization: Bearer header
401invalid_request_errorinvalid_api_keyMalformed key, or no such key
403invalid_request_errorkey_revokedThe key was revoked
404invalid_request_errormodel_not_foundUnknown or disabled model; param is model
404invalid_request_errorunknown_urlNo such endpoint
413invalid_request_errornullRequest body over 2 MB
429rate_limit_errorrate_limit_exceededRequests/min or tokens/min window exhausted
500api_errorinternal_errorBug on our side
502api_errorupstream_errorThe model provider failed or was unreachable

Examples

Validation — note param:

{ "error": { "message": "Too big: expected number to be <=2 (at `temperature`)", "type": "invalid_request_error", "code": null, "param": "temperature" } }

Unknown model:

{ "error": { "message": "The model `gpt-4o` does not exist or you do not have access to it.", "type": "invalid_request_error", "code": "model_not_found", "param": "model" } }

Upstream failure — the provider’s own message is passed through when it sends one:

{ "error": { "message": "model not found", "type": "api_error", "code": "upstream_error", "param": null } }

Retry guidance

StatusRetry?
400, 404, 413No — fix the request
401No — fix the key
403No — the key is revoked; create a new one
429Yes — wait Retry-After seconds
500Yes — a couple of attempts with backoff
502Yes — the provider may be briefly unavailable

The OpenAI SDKs already do this. Rolling your own:

import time import openai def with_retries(call, attempts=4): for attempt in range(attempts): try: return call() except openai.RateLimitError as error: wait = float(error.response.headers.get("retry-after", 2 ** attempt)) time.sleep(wait) except (openai.APIStatusError, openai.APIConnectionError) as error: status = getattr(error, "status_code", 500) if status < 500: raise # 4xx will not fix itself time.sleep(2 ** attempt) raise RuntimeError("out of retries")

Retry 429 and 5xx only, respect Retry-After, and add jitter if many workers share one key — otherwise they all retry in lockstep and hit the limit together.

Streaming errors

Errors before the first chunk arrive as JSON with a status code. Once the stream has started the status is already 200, so a later failure just ends the stream: a stream that stops without a finish_reason is incomplete. See Streaming.