
OAuth client credentials
You can create an OAuth client from your developer settings. The OAuth client starts in a “pending” state and must be reviewed by a Cal.com admin before it can be used. You must select at least one scope when creating the client. You can register up to 10 redirect URIs per client.OAuth scopes
Scopes control which API endpoints your OAuth token can access. When a user authorizes your client, the issued access token can only call endpoints covered by the granted scopes. Any request to an endpoint outside those scopes is rejected. You must select your scopes when creating your OAuth client, and include them in the authorization URL.Available scopes
| Scope | Description | What it covers |
|---|---|---|
EVENT_TYPE_READ | View event types | Listing and viewing event types, their private links, and webhooks |
EVENT_TYPE_WRITE | Create, edit, and delete event types | Creating, updating, and deleting event types, private links, and webhooks |
BOOKING_READ | View bookings | Listing bookings, viewing recordings, transcripts, calendar links, references, and attendees |
BOOKING_WRITE | Create, edit, and delete bookings | Adding guests and attendees, updating locations, confirming, declining, and reassigning bookings |
SCHEDULE_READ | View availability | Listing and viewing schedules and out-of-office entries |
SCHEDULE_WRITE | Create, edit, and delete availability | Creating, updating, and deleting schedules and out-of-office entries |
APPS_READ | View connected apps and calendars | Listing connected calendars, checking busy times, checking ICS feeds, verifying calendar connections, and viewing conferencing apps |
APPS_WRITE | Connect and disconnect apps | Saving ICS feeds, connecting calendars via OAuth, saving Apple calendar credentials, disconnecting calendars, connecting and disconnecting conferencing apps, and managing selected and destination calendars |
PROFILE_READ | View personal info | Viewing the authorized user’s profile |
PROFILE_WRITE | Edit personal info | Updating the authorized user’s profile |
Some endpoints like creating, cancelling, and rescheduling bookings are public and do not require any scope.
Team scopes
Team scopes control access to team-level resources. These apply to endpoints under/v2/teams/:teamId/... and /v2/organizations/:orgId/teams/:teamId/....
| Scope | Description |
|---|---|
TEAM_EVENT_TYPE_READ | View team event types |
TEAM_EVENT_TYPE_WRITE | Create, edit, and delete team event types |
TEAM_BOOKING_READ | View team bookings |
TEAM_BOOKING_WRITE | Create, edit, and delete team bookings |
TEAM_SCHEDULE_READ | View team schedules |
TEAM_SCHEDULE_WRITE | Create, edit, and delete team schedules |
TEAM_PROFILE_READ | View team profiles |
TEAM_PROFILE_WRITE | Create, edit, and delete teams |
TEAM_MEMBERSHIP_READ | View team memberships |
TEAM_MEMBERSHIP_WRITE | Create, edit, and delete team memberships |
Organization scopes
Organization scopes control access to organization-wide resources. These apply to endpoints under/v2/organizations/:orgId/... that do not target a specific team.
An
ORG_ scope automatically grants the corresponding TEAM_ scope. For example, a token with ORG_PROFILE_READ can also access endpoints that require TEAM_PROFILE_READ.| Scope | Description |
|---|---|
ORG_EVENT_TYPE_READ | View all event types across the organization |
ORG_EVENT_TYPE_WRITE | Create, edit, and delete event types across the organization |
ORG_BOOKING_READ | View all bookings across the organization |
ORG_BOOKING_WRITE | Create, edit, and delete bookings across the organization |
ORG_SCHEDULE_READ | View schedules across the organization |
ORG_SCHEDULE_WRITE | Create, edit, and delete schedules across the organization |
ORG_PROFILE_READ | View organization teams |
ORG_PROFILE_WRITE | Create, edit, and delete organization teams |
Authorize
To initiate the OAuth flow, direct users to the following authorization URL:| Parameter | Required | Description |
|---|---|---|
client_id | Yes | Your OAuth client ID |
redirect_uri | Yes | Where users will be redirected after authorization. Must match one of your registered redirect URIs. |
state | Recommended | A securely generated random string to mitigate CSRF attacks |
scope | Yes | Space or comma-separated list of scopes (e.g. BOOKING_READ BOOKING_WRITE). Must be a subset of scopes enabled on your OAuth client. |
code_challenge | For public clients | PKCE code challenge (S256 method) |
redirect_uri with the authorization code and state as URL parameters.
Exchange token
Exchange the authorization code for access and refresh tokens. Endpoint:POST https://api.cal.com/v2/auth/oauth2/token
Request body:
| Parameter | Description |
|---|---|
client_id | Your OAuth client ID |
client_secret | Your OAuth client secret |
grant_type | Must be authorization_code |
code | The authorization code received in the redirect URI |
redirect_uri | Must match the redirect URI used in the authorization request |
Access tokens expire after 30 minutes. Use the refresh token to get a new access token.
Refresh token
Refresh an expired access token using your refresh token. Endpoint:POST https://api.cal.com/v2/auth/oauth2/token
Request body:
| Parameter | Description |
|---|---|
client_id | Your OAuth client ID |
client_secret | Your OAuth client secret |
grant_type | Must be refresh_token |
refresh_token | The refresh token from a previous token response |
Scopes are preserved from the original authorization. You do not need to re-request scopes when refreshing tokens.
Client secret rotation
You can rotate your client secret with zero downtime. Cal.com allows up to 2 active secrets at a time, so you can deploy a new secret before revoking the old one.Generate a new secret
Go to your OAuth client settings and generate a new secret. Your old secret continues to work.
Existing access and refresh tokens remain valid after secret rotation. Rotation only affects requests that require
client_secret (token exchange and refresh).Verify access token
To verify the correct setup and functionality of OAuth credentials, use the following endpoint:GET https://api.cal.com/v2/me
Headers:
- Authorization: Bearer YOUR_ACCESS_TOKEN
Legacy client migration
If your OAuth client was created before scopes were introduced, it is a legacy client. Tokens from legacy clients can access any resource on behalf of the authorizing user without scope restrictions. You can migrate a legacy client to use explicit scopes without creating a new client:Update your authorization URL
Add a
scope parameter to your authorization URL before changing any client settings. New tokens will carry only the scopes you specify.