calcom/cal.com
REST v2
The official, documented public API. Implemented as a separate NestJS service in apps/api/v2.
Surface
Resources currently exposed (from apps/api/v2/src/modules/):
api-keys, apps, atoms, auth, booking-seat, cal-unified-calendars,
conferencing, credentials, deployments, destination-calendars,
email, event-types, jwt, kysely, memberships, oauth-clients, ooo,
organizations, prisma, profiles, redis, selected-calendars, slots,
stripe, teams, timezones, tokens, users, verified-resources, webhooksVersioned endpoints under apps/api/v2/src/platform/ use date-based suffixes (event-types_2024_06_14, bookings/2024-08-13, ...) so breaking changes can be introduced behind a new version while existing clients stay on the old one.
Authentication
Three flows:
| Flow | Use case | Module |
|---|---|---|
| API key | Long-lived bearer tokens (Authorization: Bearer cal_...) |
apps/api/v2/src/modules/api-keys (legacy: packages/features/api-keys-legacy) |
| OAuth 2.0 | Platform tenants | apps/api/v2/src/modules/oauth-clients, tokens |
| JWT | Service-to-service (short-lived) | apps/api/v2/src/modules/jwt |
OAuth requires a registered Platform "OAuth client" with a clientId + clientSecret. Each client gets its own scope of users, event types, and bookings.
Rate limiting
Every request goes through CustomThrottlerGuard (apps/api/v2/src/lib/throttler-guard.ts), backed by Redis. The configuration in apps/api/v2/src/app.module.ts keeps a dummy throttler entry registered so the guard runs; actual policy is in the guard.
Body parsers
Different routes need different body parsers:
RawBodyMiddlewarefor Stripe / billing webhooks (/v2/billing/webhook) and Vercel deployment webhooksUrlencodedBodyMiddlewarefor OAuth token endpoints (/v2/auth/oauth2/token)JsonBodyMiddlewarefor everything else
These are configured in app.module.ts via MiddlewareConsumer.
Documentation
Swagger decorators on controller methods feed apps/api/v2/src/swagger/ which generates the OpenAPI spec at apps/docs/content/api-reference/v2/openapi.json. The MintLify docs site renders that spec as the public API reference. The openapi.json file is one of the most-changed files in the repo (top 10 churn last 90 days), because every new endpoint regenerates it.
Testing
Almost every controller has an *.e2e-spec.ts neighbor. There are 42 such e2e specs. CI runs them via .github/workflows/e2e-api-v2.yml.
Legacy v1
apps/web/pages/api/v1/ retains a subset of legacy endpoints for backward compatibility. New work should go to v2. The apps/api/index.js proxy handles routing where needed.
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.