init.Tasks openapi.json inittasks.com

the buckets, the headers, and how to behave

Rate limits

Every response carries the current state of the bucket it charged:

http
RateLimit-Limit: 600
RateLimit-Remaining: 587
RateLimit-Reset: 1789459620

On a refusal you also get Retry-After, in seconds, and a rate_limited problem body.

The headers are on EVERY response, not just refusals — a client that can see its remaining budget can slow down before it is cut off. One that only learns at the 429 has no way to behave well.

The buckets

bucket limit
per credential, all requests 600 / 5 min
per credential, writes 120 / 5 min
POST /oauth/token 60 / min / IP
POST /oauth/register 10 / hour / IP
approval code lookup 10 / min / user, 30 / min / IP
POST /keys 10 / day / user
POST /webhooks 20 / hour / user
per IP, at the edge 20 req/s, burst 100

Windows are fixed, not sliding. A burst that straddles a boundary can spend two windows' worth; that is a deliberate trade for counters that survive a restart.

Behaving well

  1. Read RateLimit-Remaining and slow down. Do not wait for the 429.
  2. On 429, sleep Retry-After. Not a guess, not immediately.
  3. Back off exponentially on 5xx, with jitter, so a restart does not gather every client into one thundering retry.
  4. Use updated_since rather than re-reading everything. A full re-read on a timer is the usual reason an integration hits the limit at all.
  5. Prefer a webhook to a tight poll — but keep a slow reconciliation poll, because inbound delivery is best-effort.

If you need more

The limits are tunable and currently generous relative to what real integrations use. If you are hitting one legitimately, say what you are building.