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: 1789012800RateLimit-Limit
Requests allowed in the window.
RateLimit-Remaining
Requests left in the current window.
RateLimit-Reset
Unix timestamp when the window resets.
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?