Admission limits each caller to 30 requests per minute within an
organization. Exceeding it returns 429 with the code rate_limit. The window
is one minute. Separate source and global protections run before key authentication
and can also return 429. Honor Retry-After when supplied and use exponential
backoff with jitter.
import time, random
for attempt in range(5):
try:
return client.chat.completions.create(...)
except RateLimitError:
time.sleep(min(2 ** attempt, 30) + random.random())Spend ceilings are not rate limits#
Spending and policy refusals arrive with a different status and clear differently. None of these is a 429, and no amount
of backoff clears them:
| Status | Code | Means | Clears when |
|---|---|---|---|
403 |
key_limit |
the key's own spending limit is spent | its reset window rolls (daily, weekly, monthly) — lifetime never resets |
403 |
budget_limit |
an invocation policy's dailyMicro / monthlyMicro ceiling is reached |
the policy's day or month rolls, or the Owner raises it |
403 |
policy_denied |
an invocation policy refused the model or the output size | the policy changes |
402 |
insufficient_budget |
the project wallet cannot fund the reservation | an Owner tops up the project |
Key spending limits are set at key creation.
Invocation policies (allowedModels, dailyMicro, monthlyMicro,
maxOutputTokens) are named restrictions managed by the organization Owner — all
active policies that apply to a call remain in force at once. The project wallet
is always the hard bound underneath both. See
Caps and spend controls.
Next#
- Errors — every code and its recovery
- Caps and spend controls — bounding spend rather than rate