Rate limits
Throttle windows enforced on the public StarPlan endpoints
The public StarPlan endpoints (catalog, week, iCal, changes) sit behind @nestjs/throttler with three rolling windows applied per client IP:
| Window | Max requests |
|---|---|
| 1 second | 10 |
| 1 minute | 60 |
| 1 hour | 1 000 |
These limits apply to every public read endpoint, regardless of whether you send an X-API-Key. The presence of an API key does not raise the limit — keys exist for webhook subscription and usage telemetry, not throttle exemption.
The developer (/v1/starplan/developers/*) and webhook (/v1/starplan/webhooks*) endpoints are not currently rate-limited at the application layer — only the upstream Cloudflare and platform-level limits apply. Treat them as low-volume management endpoints; do not poll them.
Identification
Rate limits key on the requesting IP address (@nestjs/throttler default). Behind a CDN or reverse proxy, the platform reads the original client IP from the X-Forwarded-For header chain, so a single client cannot bypass the limit by routing through an intermediary.
Exceeding a window
The throttler responds with 429 Too Many Requests and standard Retry-After semantics. The error envelope follows the same shape as other API errors — see Errors.
{
"error": {
"code": "TOO_MANY_REQUESTS",
"message": "ThrottlerException: Too Many Requests",
"details": {}
}
}What to do
- Cache aggressively. Catalog data (programs, semesters, courses, rooms, instructors) changes at most once per StarPlan sync cycle. Cache it for at least an hour.
- Use the iCal feed for calendar consumers. It already carries
Cache-Control: public, max-age=600, and a 365-day horizon means one fetch covers an entire year. - Use webhooks instead of polling for change events. A webhook subscription is cheaper than scraping
/changeson a timer — see Webhooks. - Batch your reads. Prefer
/courses?periodId=…over fetching each course one by one. - Backoff on 429. Respect
Retry-After; do not hammer.
The previous splan-api documentation referenced separate anonymous and API-key tiers (5/30/200 vs 10/60/1000). That distinction was retired with the migration to /v1/starplan — only the unified 10/60/1000 tier remains.