Skip to content

Rate limits

A rate limit protects the API on a per-key basis: requests are counted per API key in a fixed one-minute window. Read and write requests have separate limits (independent counters):

Operation Method Default limit
Read GET 120 / minute
Write POST, PATCH, DELETE 60 / minute

The two buckets are independent — heavy reading never uses up your write budget, and vice versa. The RateLimit-* headers on each response reflect the bucket for that request’s method.

Every response carries the current limit state, so you can throttle proactively instead of waiting for a 429:

RateLimit-Limit: 120
RateLimit-Remaining: 117
RateLimit-Reset: 42
  • RateLimit-Limit — the ceiling for the current window.
  • RateLimit-Remaining — requests left in the current window.
  • RateLimit-Reset — seconds remaining until the window resets and Remaining refills (delta-seconds, per the IETF draft). It matches Retry-After on a 429.

Treat these headers as the source of truth — the exact limit may change over time, so read it from RateLimit-Limit rather than hard-coding 120.

Once Remaining hits 0, further requests in that window get 429 Too Many Requests (rate_limit_error / too_many_requests) with a Retry-After header:

HTTP/1.1 429 Too Many Requests
Retry-After: 2
RateLimit-Reset: 42
  • Respect Retry-After — wait the indicated number of seconds, then retry.
  • Use exponential backoff with jitter for repeated throttling.
  • Better: watch RateLimit-Remaining and slow down before you hit 0.

Event list endpoints require a from/to range no longer than 31 days — the same window as GET /tasks?view=by_date and /agenda. A wider range is rejected with 422 validation_error (invalid_request). For a year, page through it month by month.

Listings that expand repeating series into occurrences (GET /scheduled-events in every view, GET /tasks?view=by_date) expand at most 500 series per request. A scope with more repeating records is rejected with 422 validation_error — narrow it with project_id.