For the complete documentation index, see llms.txt. This page is also available as Markdown.

Rate Limits & Policies

Request budgets, page caps, and the headers that report them.

Data Endpoints

Limit

300 requests per minute, per district

Window

1 minute, rolling

Scope

The district, not the credential

Exceeded

429 Too Many Requests

The budget belongs to the district, so every credential and every process you run draws from the same pool. Two nightly jobs against the same district share 300 requests per minute between them.

At the maximum page size of 100 records, 300 requests per minute is roughly 30,000 records a minute — comfortably more than a well-behaved sync needs.

Token Endpoint

POST /api/v2/token has its own, much tighter limit:

Limit

15 requests per 5 minutes

Keyed on

client_id + IP address

This exists to blunt credential guessing. Since tokens last two hours, a correct client needs only a handful per day — if you are anywhere near this limit, you are minting a token per request instead of caching one. See Handling Expiry.

Rate Limit Headers

Successful responses carry your current budget. Both the IETF and the legacy X- prefixed families are sent, with identical values; use whichever your HTTP client already understands.

RateLimit-Limit: 300
RateLimit-Remaining: 287
RateLimit-Reset: 1789012800

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1789012800
Header
Meaning

RateLimit-Limit

Requests allowed in the window.

RateLimit-Remaining

Requests left in the current window.

RateLimit-Reset

Unix timestamp when the window resets.

These headers are best-effort. If the counter is briefly unavailable the request still succeeds but the headers may be absent — so treat them as advisory and always handle a 429 regardless of what RateLimit-Remaining last said.

Handling a 429

A 429 includes Retry-After, in seconds. Wait at least that long:

Because the window is one minute, Retry-After will never exceed ~60 seconds.

Staying Under the Limit

Use page[size]=100. The single most effective change: one request for 100 records instead of four for 25.

Sync incrementally. Where filter[updated_since] is available, fetch only what changed rather than the whole dataset. See Filtering by Modification Time.

Cache tokens. One token serves two hours of requests.

Serialise your requests. Parallel workers hit the shared district budget much faster than you would expect. Start sequential and add concurrency only if you need it — while watching RateLimit-Remaining.

Schedule off-peak. Bulk extracts during the school day compete with teachers using the product.

Back off on 429, don't retry tightly. A retry loop with no delay turns one 429 into a sustained block.

Other Limits

Maximum page size

100 records

Default page size

25 records

Token lifetime

2 hours (or the credential's expiry, whichever is sooner)

Data Policies

Read-only. GET only. No endpoint modifies data.

District isolation. A credential reads exactly one district's data. Ids from another district return 404.

Withheld data. Answer keys, correct answers, individual student responses and section SIS identifiers are not exposed by any endpoint at any scope. See Key Concepts.

Student data. Responses may contain personally identifiable student information. Handle it in line with your district's obligations — FERPA and any applicable state privacy law. Encrypt it at rest, restrict access to it, and do not send it to third-party services without the appropriate agreements.

Auditing. API access is logged. Requests are attributable to the credential that made them, which is a reason to use separate credentials for separate integrations rather than sharing one.

Availability

Check status.instructure.com for incidents. Treat 5xx responses as transient and retry with exponential backoff.

Last updated

Was this helpful?