Skip to main content
Limits are per key, per hour, counted separately for reads and writes. Reads are GET. Writes are POST, PATCH and DELETE. The two quotas are independent — exhausting your writes leaves reads working.

Headers

Every response carries your current standing, including errors:
X-RateLimit-Reset is Unix time in seconds. On a 429 you also get:
Honour Retry-After rather than writing your own backoff — it’s the header every HTTP client library already knows how to respect, and it means you don’t have to parse our error body to know when to try again.

Staying inside the limits

Quotas are per key, so an ATS sync and a nightly report export on separate keys can’t starve each other. You can also revoke one without disturbing the other.
Grading takes minutes, not seconds. Polling a submission every few seconds burns quota to no benefit — every 30–60 seconds is plenty, and only for submissions actually awaiting a report.
GET /v1/submissions?assessment_id=…&status=evaluated&since=… costs one request. Fetching everything and filtering in your code costs many, and gets worse as you grow.
A busy attempt produces thousands of events, and a full walk at 500 per page can be several requests for a single submission. Pull events only when you need the detail, not as part of a routine sync.

Other limits

Not rate limits, but the other ceilings worth knowing:
  • Request body: 512 KB. Every documented body is well under a kilobyte; the headroom is for a large selected_task_ids array.
  • Page size: 100 (500 for events). Over the max is a 400, not a silent clamp.
  • Active API keys: 20 per organization.
Limits are per key rather than per organization, so more keys means more total quota. That is not a workaround to lean on — if you need materially more throughput, talk to us rather than minting keys to farm quota.