Getting Started
At a glance
- Methods — GET only
- Auth — No API key
- Rate limits — 500/min per endpoint path; +60/min heavy; health excluded
- Caching — ETag + Cache-Control; If-None-Match for 304
Authentication
No API key required. Send unauthenticated GET requests.
Rate limits
Production enforces per-IP limits via Cloudflare Workers Rate Limiting (per edge location):
- 500 requests / 60 seconds per endpoint path (e.g.
/api/v1/calendarand/api/v1/todayhave separate counters). - 60 requests / 60 seconds additional heavy bucket when
all=trueon calendar/meta, orallSessions=trueon calendar. GET /api/healthandGET /mcp/healthare not rate limited (uptime monitors).
Successful responses and 429 include X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, RateLimit, and RateLimit-Policy. Remaining is best-effort (approximate per worker isolate). On 429, use Retry-After (seconds until the current window resets) and JSON retryAfter.
Rate-limit status
GET /api/v1/rate-limit
Returns published policies and a best-effort remaining quota for the caller. This call does not consume rate-limit budget. Optional pathname selects which route to inspect (defaults to this endpoint). Optional heavy=true includes the heavy bucket in the primary view.
Query parameters
| Name | Type | Description | Example |
|---|---|---|---|
pathname | string | API path to inspect. Must start with /. Defaults to /api/v1/rate-limit. | /api/v1/calendar |
heavy | string | When true (or "1"/"yes"), response highlights the heavy bucket alongside endpoint policy. | true |
Response fields
| Field | Type | Description | Example |
|---|---|---|---|
enforcement | string | How limits are applied. Remaining is per edge isolate and approximate. | Cloudflare Workers Rate Limiting (per edge location). Remaining counts are approximate per worker isolate and do not consume quota on this endpoint. |
pathname | string | Path being inspected. | /api/v1/calendar |
heavyMode | boolean | Whether the heavy bucket is highlighted. | false |
policies | object[] | Published endpoint (500 / 60s) and heavy (60 / 60s) policies. | [{ "name": "endpoint", "limit": 500, "period": 60 }] |
endpoint | object | Snapshot: limit, remaining, reset, retryAfter. | { "name": "endpoint", "limit": 500, "remaining": 499 } |
heavy | object | Same shape for the heavy bucket. | { "name": "heavy", "limit": 60, "remaining": 60 } |
How to start
- Call Sessions & programs (meta) for session options; Public holiday options (meta) for holiday filters.
- Request Calendar activities, Lecture weeks (1-14), or Malaysia public holidays data.
- Use Playground to test live.
Errors: validation 400; rate limits 429; missing session 404 on calendar and lecture-weeks.
Agent skills
The bilauitmcuti-api agent skill teaches coding assistants how to call this API — endpoints, query parameters, ETags, and rate limits — in one short reference.
Why use it: agents guess less. They pick the right paths, send required session / group params, and respect caching and rate-limit headers instead of inventing URLs from partial context.
How to use: install the skill from bilauitmcuti/skills in Cursor or another agent that supports skills, or open the skill page below.
Model Context Protocol (MCP)
Point AI assistants — ChatGPT, Claude, Cursor — at this API with MCP. The server is hosted at https://mcp.bilauitmcuti.com/mcp (Streamable HTTP), so there is nothing to install. It is read-only, so nothing can be changed.
Contact & feedback
Questions about the API, product feedback, or reports of wrong or mismatched calendar data — email hello@bilauitmcuti.com or send a message on Threads threads.com/@bilauitmcuti.