Errors & rate limits
All errors are returned as JSON, regardless of your Accept header.
401 — Unauthorized
No credential was supplied:
{
"error": "Unauthorized",
"message": "Authentication required. Please provide a valid Bearer token in the Authorization header."
}
The credential was rejected — wrong token, expired, revoked, or deleted:
{
"error": "Unauthorized",
"message": "Invalid or expired token."
}
The API deliberately does not distinguish between these causes. If you get a persistent 401:
- Check the header format —
Authorization: Bearer <token>, one space, no quotes, and no trailing newline from a shell variable. - Ask an administrator to confirm the token is active and unexpired.
404 — Not Found
The course or class does not exist, or is not public. This is expected in normal operation; render a "not available" page rather than an error.
422 — Unprocessable Entity
A query parameter failed validation — an unknown type, or a limit above 50.
{
"message": "The given data was invalid.",
"errors": {
"limit": ["The limit may not be greater than 50."]
}
}
429 — Too Many Requests
Rate limit exceeded. See Rate limits below.
500 — Internal Server Error
Most commonly caused by a malformed date filter — a value that is neither MM-DD-YYYY nor the literal invalid date. Validate date input before sending it.
Rate limits
All API requests share a limit of 60 requests per minute per client. Exceeding it returns 429 with Retry-After and X-RateLimit-* headers.
Sixty per minute is comfortable for a server-rendered site but not for a page that fans out one request per course. Recommendations:
- Cache aggressively. Course catalogues change daily, not per-second. A 5–15 minute cache on
/public/coursesand/public/popularremoves almost all traffic. - Call from your server, not the browser. This protects the token and keeps the limit tied to one predictable caller.
- Prefer the list endpoints.
/public/coursesreturns every course with its next class in one request; fetching courses individually is both slower and limit-hungry. - Back off on
429. HonourRetry-Afterand retry once rather than hammering.