Rate limits
A key has a rate a minute and an optional cap a month. Read the headers, and wait Retry-After on a 429.
A call made with a key is counted against two limits that belong to the key and are shared by every caller using it, whatever their address. They are set when the key is made and can be changed in Settings.
| Limit | Refills | On breach |
|---|---|---|
| Requests a minute | Continuously, at the pace of the limit. A key can burst a minute's worth. | 429 rate-limited, Retry-After in seconds. |
| Requests a month (optional) | On the first of the month, UTC. | 429 monthly-cap-reached, Retry-After until then. |
| Limit | Default | Least | Most |
|---|---|---|---|
| Requests a minute | 120 | 1 | 600 |
| Requests a month | None | 1 | 1,000,000 |
| Lifetime | 3 months | 1 week | 5 years |
Headers
Every answer to a call made with a key says where you stand, in the structured syntax of draft-ietf-httpapi-ratelimit-headers-11:
RateLimit-Policy: "key";q=120;w=60
RateLimit: "key";r=87;t=12q is the quota and w its window in seconds; r is what is left and t the seconds until it is whole again. A key with a monthly cap lists a second item, "month". A limit that refuses stops the check, so a request the minute refused never spends the month.
Handling a 429
- Stop sending. Read
Retry-After, in whole seconds, and wait at least that long. - Then retry. Add a little jitter if many workers share the key, so they do not all return together.
- Poll a run at the
Retry-Afterit gives, not faster; a run changes about once a second at most. - If
monthly-cap-reachedis a surprise, raise the cap in Settings, or find which job is spending it in the usage report.
async function call(url: string, init: RequestInit, tries = 5): Promise<Response> {
for (let attempt = 1; ; attempt++) {
const response = await fetch(url, init)
if (response.status !== 429 || attempt === tries) return response
const wait = Number(response.headers.get('Retry-After') ?? 1)
await new Promise((resolve) => setTimeout(resolve, (wait + Math.random()) * 1000))
}
}Other caps
Some work has its own cap, independent of the key, and answers 429 too. These carry no RateLimit headers, which is how to tell them apart from the key's own:
- Starting runs: 60 an hour per person, and 3 in flight at once (
rate-limited,too-many-active). - Invitations: 30 a day per org, across Settings and the API (
invite-cap-reached).