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/calendar and /api/v1/today have separate counters).
  • 60 requests / 60 seconds additional heavy bucket when all=true on calendar/meta, or allSessions=true on calendar.
  • GET /api/health and GET /mcp/health are 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

NameTypeDescriptionExample
pathnamestringAPI path to inspect. Must start with /. Defaults to /api/v1/rate-limit./api/v1/calendar
heavystringWhen true (or "1"/"yes"), response highlights the heavy bucket alongside endpoint policy.true

Response fields

FieldTypeDescriptionExample
enforcementstringHow 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.
pathnamestringPath being inspected./api/v1/calendar
heavyModebooleanWhether the heavy bucket is highlighted.false
policiesobject[]Published endpoint (500 / 60s) and heavy (60 / 60s) policies.[{ "name": "endpoint", "limit": 500, "period": 60 }]
endpointobjectSnapshot: limit, remaining, reset, retryAfter.{ "name": "endpoint", "limit": 500, "remaining": 499 }
heavyobjectSame shape for the heavy bucket.{ "name": "heavy", "limit": 60, "remaining": 60 }

How to start

  1. Call Sessions & programs (meta) for session options; Public holiday options (meta) for holiday filters.
  2. Request Calendar activities, Lecture weeks (1-14), or Malaysia public holidays data.
  3. 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.