> ## Documentation Index
> Fetch the complete documentation index at: https://coss-mintlify-0e24fcb1.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# How to use OAuth to authorize apps with Cal.com accounts

> Set up OAuth to let your app access Cal.com on behalf of users, with scoped permissions for bookings, calendars, schedules, webhooks, routing forms, workflows, and more.

As an example, you can view our OAuth flow in action on Zapier. Try to connect your Cal.com account [here](https://zapier.com/apps/calcom/integrations). To enable OAuth in one of your apps, you will need a Client ID, Client Secret, Authorization URL, Access Token Request URL, and Refresh Token Request URL.

<Frame>
  <img src="https://mintcdn.com/coss-mintlify-0e24fcb1/0nroDa6UH_pzQXSt/images/oauth-zapier.png?fit=max&auto=format&n=0nroDa6UH_pzQXSt&q=85&s=e202d894a3516106d250c05a7906c392" alt="" width="1092" height="824" data-path="images/oauth-zapier.png" />
</Frame>

## OAuth client credentials

You can create an OAuth client from your [developer settings](https://app.cal.com/settings/developer/oauth). 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 and their private links                                                          |
| `EVENT_TYPE_WRITE`         | Create, edit, and delete event types   | Creating, updating, deleting event types and managing private links                                              |
| `BOOKING_READ`             | View bookings                          | Listing bookings, viewing recordings, transcripts, calendar links, and references                                |
| `BOOKING_WRITE`            | Create, edit, and delete bookings      | Adding guests, updating locations, confirming, declining, and reassigning bookings                               |
| `SCHEDULE_READ`            | View availability                      | Listing and viewing schedules                                                                                    |
| `SCHEDULE_WRITE`           | Create, edit, and delete availability  | Creating, updating, and deleting schedules                                                                       |
| `APPS_READ`                | View connected apps and calendars      | Listing connected calendars, checking busy times, checking ICS feeds, and verifying calendar connections         |
| `APPS_WRITE`               | Connect and disconnect apps            | Saving ICS feeds, connecting calendars via OAuth, saving Apple calendar credentials, and disconnecting calendars |
| `PROFILE_READ`             | View personal info                     | Viewing the authorized user's profile                                                                            |
| `PROFILE_WRITE`            | Edit personal info                     | Updating the authorized user's profile                                                                           |
| `WEBHOOK_READ`             | View webhooks                          | Listing and viewing webhooks                                                                                     |
| `WEBHOOK_WRITE`            | Create, edit, and delete webhooks      | Creating, updating, and deleting webhooks                                                                        |
| `VERIFIED_RESOURCES_READ`  | View verified emails and phone numbers | Listing verified email addresses and phone numbers                                                               |
| `VERIFIED_RESOURCES_WRITE` | Verify emails and phone numbers        | Requesting verification codes and verifying email addresses and phone numbers                                    |

<Note>
  Some endpoints like creating, cancelling, and rescheduling bookings are public and do not require any scope.
</Note>

### 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            |
| `TEAM_APPS_READ`                | View team connected apps                             |
| `TEAM_APPS_WRITE`               | Connect and disconnect team apps                     |
| `TEAM_ROUTING_FORM_READ`        | View team routing forms                              |
| `TEAM_ROUTING_FORM_WRITE`       | Create, edit, and delete team routing form responses |
| `TEAM_WORKFLOW_READ`            | View team workflows                                  |
| `TEAM_WORKFLOW_WRITE`           | Create, edit, and delete team workflows              |
| `TEAM_VERIFIED_RESOURCES_READ`  | View team verified emails and phone numbers          |
| `TEAM_VERIFIED_RESOURCES_WRITE` | Verify emails and phone numbers for teams            |

### 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.

<Note>
  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`.
</Note>

| 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                  |
| `ORG_MEMBERSHIP_READ`    | View organization memberships and users                      |
| `ORG_MEMBERSHIP_WRITE`   | Create, edit, and delete organization memberships and users  |
| `ORG_ROUTING_FORM_READ`  | View organization routing forms                              |
| `ORG_ROUTING_FORM_WRITE` | Create, edit, and delete organization routing form responses |
| `ORG_WEBHOOK_READ`       | View organization webhooks                                   |
| `ORG_WEBHOOK_WRITE`      | Create, edit, and delete organization webhooks               |

## Authorize

To initiate the OAuth flow, direct users to the following authorization URL:

```
https://app.cal.com/auth/oauth2/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&state=YOUR_STATE&scope=BOOKING_READ%20BOOKING_WRITE
```

### Rotating client secrets

You can rotate your OAuth client secret without downtime. Cal.com supports up to two active secrets per client at the same time, so you can transition gracefully.

<Steps>
  <Step title="Generate a new secret">
    In your Cal.com dashboard, go to your OAuth client settings and create a new secret. Both your old and new secrets are now valid.
  </Step>

  <Step title="Update your application">
    Replace the old `client_secret` value in your application with the new one. Verify that token exchanges and refreshes work with the new secret.
  </Step>

  <Step title="Delete the old secret">
    Once your application is using the new secret, delete the old one from your OAuth client settings.
  </Step>
</Steps>

<Warning>
  You cannot delete your last remaining secret. Confidential OAuth clients must always have at least one active secret.
</Warning>

### Authorization URL

**URL parameters:**

| 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)                                                                                                     |

After users click **Allow**, they are redirected to your `redirect_uri` with the authorization `code` as a URL parameter. If you included a `state` parameter in the authorization URL, it is returned unchanged so you can verify the response matches the original request.

## 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 |

**Response:**

```json theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "expires_in": 1800,
  "scope": "BOOKING_READ BOOKING_WRITE"
}
```

<Note>
  Access tokens expire after 30 minutes. Use the refresh token to get a new access token.
</Note>

## 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 |

**Response:**

```json theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "expires_in": 1800,
  "scope": "BOOKING_READ BOOKING_WRITE"
}
```

<Note>
  Scopes are preserved from the original authorization. You do not need to re-request scopes when refreshing tokens.
</Note>

## 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.

<Steps>
  <Step title="Generate a new secret">
    Go to your [OAuth client settings](https://app.cal.com/settings/developer/oauth) and generate a new secret. Your old secret continues to work.
  </Step>

  <Step title="Update your application">
    Use the new secret in all token exchange and refresh requests.
  </Step>

  <Step title="Revoke the old secret">
    Once you've verified the new secret works, revoke the old one from the settings page. Revocation takes effect immediately.
  </Step>
</Steps>

<Note>
  Existing access and refresh tokens remain valid after secret rotation. Rotation only affects requests that require `client_secret` (token exchange and refresh).
</Note>

## 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:

<Steps>
  <Step title="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.
  </Step>

  <Step title="Update client scopes in settings">
    Once your authorization URL is updated and working, open your OAuth client settings and select the matching scopes. After saving, scope validation is enforced for all new authorization requests.
  </Step>
</Steps>

<Warning>
  Do not update the client scopes before updating your authorization URL. Doing so will break the authorization flow for any user visiting the old URL without a `scope` parameter.
</Warning>

Tokens issued before the migration continue to work until users re-authorize.
