Rate limits
The policies
Three limits apply to the calls that spend them. Each is per environment: every key of your live environment shares the live limits, and your test environment has its own.
The numbers depend on your plan. A limit can change while you are using the API, for example when your plan changes; the new value applies within about a minute. Reads — polling a job, fetching a result, usage and balance — are not rate limited and carry no rate-limit headers.
A refusal is a 429 with one of these codes:
The headers
Rate-limit headers are turned on per account. Until they are on for yours, responses
carry none of them, and every limit below is still enforced the same way. Handle 429
and Retry-After whether or not you see the headers.
A response that spent a policy carries the IETF structured pair
(draft-ietf-httpapi-ratelimit-headers): RateLimit-Policy names each policy’s quota
q per window w seconds, and RateLimit names what remains, r, and the seconds
until the policy is whole again, t.
The RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers carry the
same reading for clients that only understand those. They describe one policy only:
the one with the least remaining (on a tie, the later reset). Prefer the structured
pair.
A refusal carries the same headers, with r=0 for the policy that refused it:
The daily item appears only when your plan has a daily quota. Its r is advisory: it
is read just after your job was admitted, so a submission made at the same moment can
make it lag by one. The limit itself is enforced exactly.
How the per-minute limits refill
The submit and upload policies are either a fixed window, which refills all at
once when the minute ends, or a token bucket (GCRA), where each call spends one of q
tokens and tokens come back steadily, one every w / q seconds. Either way t is the
honest wait: the rest of the minute for a fixed window, the next token for the bucket.
What is not advertised
Two limits are enforced without headers: how many of your jobs may wait in the queue,
and how many may run at once. Both change as jobs start and finish, so a number in one
response would be stale by the next. A full queue answers TENANT_QUEUE_LIMIT_EXCEEDED
with Retry-After; a concurrency limit only delays when a queued job starts and never
refuses a submission.
In the SDKs
Both SDKs parse the headers, so you do not have to. Where the headers are off, the readings below are empty.
last_rate_limit / lastRateLimit holds what the last submission or upload advertised;
polling does not clear it. An error carries its own as error.rate_limit /
error.rateLimit. When a RATE_LIMITED refusal has no Retry-After, the SDKs wait the
refusing policy’s t before their retry. They never retry QUOTA_EXCEEDED. See
Retries and backoff.