Rate limits & quotas
Two per-token bounds, plus one per-IP safety net:
Burst limit
60 requests/minute per token. Exceeding it returns 429 (code rate_limited) with Retry-After: 60.
Daily quota
5,000 requests per UTC day per token. Every counted response carries X-Quota-Limit and X-Quota-Remaining; exceeding it returns 429 (code quota_exceeded) with Retry-After set to the UTC-midnight reset. GET /v1/health is never counted.
Pace long jobs off X-Quota-Remaining rather than retrying into the wall.
Per-IP fallback
An additional 300 requests/minute per client IP guards against floods. If you run several tokens from one server, they share this IP budget — space them out or spread across IPs to stay clear of it.
Caching
Heavy GETs (project, task list) return a strong ETag. Send it back as If-None-Match and an unchanged resource answers 304 Not Modified with an empty body — poll cheaply that way. Cross-origin JavaScript can read ETag, X-Total-Count, X-Trace-Id, and Retry-After (CORS-exposed).
Idempotent creates
POST endpoints that create things accept an Idempotency-Key header. Retrying with the same key and same body replays the original response — no duplicate is created. The same key with a different body is 409 idempotency_conflict. Keys are scoped to your token and project.
One caveat: a replay returns the cached original response, not a live re-read — if the resource changed or was deleted since, the replay still echoes its creation snapshot. Use a fresh key per logical create; reuse a key only to retry the identical request.
Best practices
- Back off on
429rather than retrying immediately — honor theRetry-Afterheader, whether the limiting bound was the burst limit or the daily quota. - Check the
codefield on a429(rate_limitedvsquota_exceeded) to tell a short burst apart from a day you need to pace differently. - Watch
X-Quota-Remainingon every response and slow down before you hit zero, instead of discovering the wall by getting429s.