projects.write. Each write publishes config-dirty so the gateway picks it up on the next snapshot load.
Pick a scope
Every rate limit and quota attaches at a scope. The gateway enforces the most specific policy per dimension and every applicable level, so a request can be checked against its end-user, key, environment, and project limits at once.scope_ref is required for key, model, and end_user_plan, and forbidden for the
others — sending it (or omitting it) incorrectly is a 400.1. Add a rate limit
Rate limits cap requests per second/minute/day and max concurrency. Aburst_multiplier allows short bursts while bounding the sustained rate. At least one of rps, rpm, rpd, or max_concurrency must be set.
This example caps every end user on the free plan to 20 requests/minute and 2 concurrent requests:
GET /v1/environments/{envId}/rate-limits.
2. Add a quota
A quota caps a metric over a fixed calendarwindow (day or month). The metric is one of requests, input_tokens, output_tokens, total_tokens, or cost_usd. Set mode to hard to block, or soft to alert only; a grace_pct on a hard quota admits N% overage before blocking.
This caps the project to 5,000,000 total tokens per day, hard, with 10% grace:
GET /v1/environments/{envId}/quotas.
3. Set a spend budget
A budget is a USD spend cap for the project, enforced with a reserve/settle scheme so concurrent requests cannot collectively overrun it. It is a project-level write:period—monthlyordaily; the accounting window is UTC-aligned.action_on_exceed—blockenforces the cap (a request over the cap fails402budget_error);notifyalerts without blocking.notify_thresholds— fractions of the budget at which the account owner is emailed (e.g.0.8= 80%,1.0= 100%).
GET /v1/projects/{projectId}/budget/status.
Soft vs hard: what “exceeded” does
Every threshold is either soft or hard:- Soft never blocks. Crossing it sends an email alert to the account owner (once per window per threshold) — an early warning.
- Hard rejects the request:
429rate_limit_error/quota_error, or402budget_error, withRetry-Afterwhere meaningful.
Handle the errors in your app
The SDK surfaces rate-limit state on every response and raises typed errors when a hard limit trips:insufficient_quota at 429, because the OpenAI error schema has no 402.
Related
Limits, quotas & budgets
Precedence, headers, and reconciliation.
Per-user limits tutorial
Cap an individual end user step by step.
End users & entitlements
Per-plan presets and blocking abusers.
Observability: logs & usage
Watch usage and spend against your limits.