Rate limits & budgets
RateLimit headers, 429 semantics, and per-key spend ceilings
Request rate
/v1 requests are limited per caller (per API key). Every response carries:
RateLimit-Limit: 120
RateLimit-Remaining: 87
RateLimit-Reset: 17Hitting the limit returns 429 rate_limited (retriable) with Retry-After.
Polling a run every 15s uses ~4 requests/minute — the limit exists to stop
runaway loops, not normal integrations.
Model-call limits on the free surfaces (abuse guard)
Some endpoints make a model call that is not a paid run: the intake and guidance parsers, run preflight, Blueprint onboarding infer/adjust, and report chat. These are metered per caller separately from the request rate above, so a stuck loop cannot burn tokens on work nobody is paying for:
| surface | per minute | per day | on refusal |
|---|---|---|---|
| parsers, preflight, onboarding, chat | 30 | 500 (shared) | 429 rate_limited / 429 llm_daily_limit_exceeded |
POST /v1/research/runs and /estimate with a query | 120 (matches the request limit) | 500 (shared) | 429 rate_limited |
Founders and Enterprise plans get 3× these figures. llm_daily_limit_exceeded
is a rate limit, not a billing wall — topping up does not lift it; retry
after the rolling 24h window or ask support to raise it. Sending seeds instead
of query skips the parse and is not subject to this table.
Auto-suspend. A key that keeps hitting refusals — 20 blocked calls, or 5
unparseable / off-purpose verdicts, within 10 minutes — is paused:
403 key_suspended, an audit entry, and an email to the org owner. Two paused
keys in 24h pause the owning user (403 account_suspended; suspended on
/v1/me says so up front). Stop and alert a human; do not mint a new key —
a fresh key of a paused user is refused the same way. The query parse on run
create/estimate is the one exception to the blocked-call count: a successful
parse is charged as a run, so being fast there never pauses a key — only
repeated unparseable verdicts do.
Run concurrency & credits
Separate from request rates, run creation can return:
429 run_concurrency_exceeded— your ORG's run caps, set by your own admin (/api/billing/limits). Queue and retry.402 insufficient_credits— prepaid balance too low; a human must top up.402 plan_upgrade_required— the plan does not include this capability (e.g. Max-depth runs, webhooks, the audit log). Topping up will not help; a human must upgrade. Never retry this one.402 budget_exceeded— this key's ownbudget_runs/budget_centsceiling (set in the create-key dialog or viaPOST /v1/keys).
The three codes are distinct because the correct agent response differs: back off / queue / stop and alert a human.