Rate limits

Recover from transient request-rate limits without confusing them with quota or budget exhaustion.

Rate limits control request pace for one project API key. They are separate from monthly usage quotas, hard cost budgets, credits, and billed capability work.

Every request that successfully authenticates to /v1 consumes one place in that key's rolling 60-second window. This includes reads, polling, validation failures, idempotent replays, and calls to Usage. Missing, invalid, revoked, and expired credentials do not enter a key's window because no key can be identified.

The deployment default is 120 authenticated requests per 60 seconds per API key. A deployment can configure another limit, so use the policy and live window values returned by the API:

Response valueMeaning
RateLimit-LimitRequests allowed in the current 60-second window.
RateLimit-RemainingRequests still available after the current request.
RateLimit-ResetWhole seconds until the oldest request leaves the current window.
Retry-AfterOn rate_limit_exceeded only, the minimum whole seconds to wait before retrying.

The three RateLimit-* headers appear on authenticated success and error responses. GET /v1/usage also returns rate_limit.limit and rate_limit.window_seconds for policy discovery.

The per-minute limit is set by the organization's usage tier, which grows automatically with cumulative paid usage and account age. GET /v1/usage returns the current tier as usage_tier (key, name, rank, rate_limit_per_minute, monthly_cost_cap_usd). Each tier also carries a monthly spend cap: when it is reached, job creation fails 429 budget_exceeded with error.details.scope of "usage_tier" — like budget exhaustion, this is not transient and resets at error.details.resets_at.

When request pace is too high, the API returns 429 with error.code set to rate_limit_exceeded. Wait at least the larger of Retry-After and RateLimit-Reset, then retry with bounded exponential backoff and jitter. Polling consumes request-rate capacity but does not create or bill another generation run.

quota_exceeded and budget_exceeded also return 429, but neither is a transient request-rate failure and neither carries Retry-After. Use error.details.resets_at and the counters in Limits, budgets, and usage to decide whether to wait for the next UTC month or ask an administrator to change the control. The complete decision table is in Errors.