> ## Documentation Index
> Fetch the complete documentation index at: https://cal.com/help/llms.txt
> Use this file to discover all available pages before exploring further.

# Delegation Credential — Microsoft 365

> Connect Microsoft 365 calendars for all organization members using a single Microsoft Entra ID application.

Delegation Credential lets organization admins connect Microsoft 365 (Outlook) calendars for every member at once, without each person needing to authorize individually. It uses a Microsoft Entra ID (formerly Azure AD) application with admin-granted permissions to read availability and create events on behalf of your organization's users.

<Note>
  Only organization owners and admins can create and enable a Delegation Credential. The admin's email must belong to the Microsoft 365 domain being configured.
</Note>

***

## What you need

Before starting, make sure you have:

* **Organization admin access** in Cal.com
* **Microsoft Entra admin access** to register an application and grant admin consent
* **A Microsoft 365 tenant** with the domain you want to configure

***

## Step 1: Register an application in Microsoft Entra ID

<Steps>
  <Step title="Open the Microsoft Entra admin center">
    Go to [entra.microsoft.com](https://entra.microsoft.com) and sign in with your Microsoft 365 admin account.
  </Step>

  <Step title="Create a new app registration">
    Go to **Identity → Applications → App registrations** and click **New registration**. Give your application a name (for example, `Cal.com Delegation Credential`).
  </Step>

  <Step title="Choose supported account types">
    Select **Accounts in this organizational directory only (single tenant)**. You don't need to add a redirect URI for this flow.
  </Step>

  <Step title="Register">
    Click **Register**. You'll land on the application's overview page, which shows the **Application (client) ID** and **Directory (tenant) ID**. Keep this page open — you'll need both values shortly.
  </Step>
</Steps>

***

## Step 2: Add API permissions

The application needs two Microsoft Graph **application permissions** so Cal.com can read and write calendars and resolve users by email. A third permission, `Application.ReadWrite.OwnedBy`, is only required if you want Cal.com to rotate the client secret automatically before it expires.

| Permission                      | Why Cal.com needs it                                                                                                                                                                                                                                                                                                       |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Calendars.ReadWrite`           | Read availability and create or update calendar events for members in the tenant.                                                                                                                                                                                                                                          |
| `User.Read.All`                 | Resolve the Microsoft 365 user for a Cal.com member by their email address.                                                                                                                                                                                                                                                |
| `Application.ReadWrite.OwnedBy` | Automatically rotate the client secret on the app registration Cal.com owns, before it expires. Also requires [making the application an owner of itself](#make-the-application-an-owner-of-itself). **Not required** if you [opt out of automatic secret rotation](#client-secret-rotation) and manage rotation manually. |

<Steps>
  <Step title="Open API permissions">
    From your application page, go to **API permissions** and click **Add a permission**.
  </Step>

  <Step title="Select Microsoft Graph">
    Choose **Microsoft Graph**, then **Application permissions** (not delegated).
  </Step>

  <Step title="Add the required permissions">
    Search for and add:

    * `Calendars.ReadWrite`
    * `User.Read.All`
    * `Application.ReadWrite.OwnedBy` — skip this one if you plan to [opt out of automatic secret rotation](#client-secret-rotation); if you keep it, also complete [Make the application an owner of itself](#make-the-application-an-owner-of-itself) below
  </Step>

  <Step title="Grant admin consent">
    Back on the API permissions page, click **Grant admin consent for \<your tenant>** and confirm. The status column should show a green check mark next to each permission you added.
  </Step>
</Steps>

<Warning>
  Without admin consent, Cal.com cannot use the application to access calendars. Make sure the permissions you added show **Granted** before continuing.
</Warning>

### Make the application an owner of itself

Only needed if you want automatic secret rotation. `Application.ReadWrite.OwnedBy` lets the application manage app registrations it **owns**, so granting the permission is not enough on its own — the application's own service principal has to be added as an owner of its app registration. Skipping this is the most common reason rotation looks configured but keeps failing.

The portal's **Owners** blade only accepts users, so add the ownership with the [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli), using two different object IDs:

| Value                           | Where to find it                                                                                                            |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| App registration **Object ID**  | **App registrations → your app → Overview → Object ID**. This is *not* the Application (client) ID.                         |
| Service principal **Object ID** | **Enterprise applications → the same app → Overview → Object ID**. A different value from the app registration's Object ID. |

```bash theme={null}
az login --tenant <tenantId> --allow-no-subscriptions

az ad app owner add \
  --id <applicationObjectId> \
  --owner-object-id <servicePrincipalObjectId>

# verify the service principal now shows up as an owner
az ad app owner list --id <applicationObjectId> --query "[].id"
```

<Note>
  This step needs a work or school (Entra ID) tenant — Microsoft Graph rejects it for personal/consumer Microsoft accounts.
</Note>

***

## Step 3: Create a client secret

<Steps>
  <Step title="Open Certificates & secrets">
    From your application page, go to **Certificates & secrets** and click **New client secret**.
  </Step>

  <Step title="Set a description and expiry">
    Add a description (for example, `Cal.com DWD`) and choose an expiration period that suits your security policy.
  </Step>

  <Step title="Copy the secret Value">
    Click **Add**, then immediately copy the **Value** column — not the Secret ID. You won't be able to view this value again after you leave the page.
  </Step>
</Steps>

<Warning>
  Cal.com creates its own replacement secrets with a **180-day** lifetime. If your tenant has an app management policy that caps client secret lifetimes below 180 days, Microsoft rejects every rotation attempt — exempt this app registration from the policy, raise the cap to at least 180 days, or [opt out of automatic secret rotation](#client-secret-rotation) and rotate manually.
</Warning>

***

## Step 4: Create the Delegation Credential in Cal.com

<Steps>
  <Step title="Open Delegation Credential settings">
    In Cal.com, go to **Settings → Organization → Delegation Credential**.
  </Step>

  <Step title="Add a new credential">
    Click **Add delegation credential**.
  </Step>

  <Step title="Fill in the form">
    * **Domain**: Enter your Microsoft 365 domain (for example, `acme.com` if your emails are `@acme.com`)
    * **Workspace Platform**: Select **Microsoft 365**
    * **Client ID**: Paste the **Application (client) ID** from Step 1
    * **Tenant ID**: Paste the **Directory (tenant) ID** from Step 1
    * **Client Secret**: Paste the secret **Value** you copied in Step 3
  </Step>

  <Step title="Create the credential">
    Click **Create**. The credential will be created but not yet enabled.
  </Step>
</Steps>

***

## Step 5: Enable the Delegation Credential

<Steps>
  <Step title="Toggle to enabled">
    On the Delegation Credential list, toggle the new credential to **Enabled**. Cal.com verifies that the application can authenticate against your tenant and access calendars before the credential becomes active.
  </Step>
</Steps>

<Warning>
  The admin enabling the credential must have an email address that belongs to the configured Microsoft 365 domain, and that email must be verified in Cal.com.
</Warning>

***

## What happens after enabling

Once the Delegation Credential is enabled:

* **Microsoft 365 Calendar is auto-connected** for all organization members whose email matches the configured domain — they do not need to connect it manually
* **New members** added to the organization automatically get their calendar connected
* Members **cannot disconnect** the delegation-managed calendar credential (they can still connect additional calendars manually)
* **Cal.com creates its own client secret** on the app registration and stages it as *pending*, so it can rotate that secret later. The secret you entered stays the active one until Cal.com has validated the new one — within about an hour — and swaps it in. This is why the app registration shows an extra `Cal.com managed` secret shortly after enabling, and why the secret you created isn't the one in use a day later.

***

## Client secret rotation

Microsoft Entra client secrets expire, so the credential needs a new secret before that happens. By default, Cal.com handles this automatically.

* **Automatic rotation (default)**: With `Application.ReadWrite.OwnedBy` granted and [the app owning itself](#make-the-application-an-owner-of-itself), Cal.com creates a new client secret about a week before the current one expires, validates it, and promotes it once it's confirmed to work — no action needed from you. Replacement secrets get a 180-day lifetime, and the secret being replaced is left to expire on its own instead of being deleted. See [Set up automatic secret rotation](/help/enterprise/delegation-credential-microsoft-365-secret-rotation) for how to enable this on a credential you already have, how to check its state through the API, and what each failure code means.
* **Manual rotation (opt-out)**: You can opt a credential out of automatic rotation if you'd rather manage secrets yourself, for example to keep full control over your app registration's credentials. This is currently only available through the [Cal.com API v2](https://cal.com/docs/api-reference/v2/introduction) — set `optOutAutoSecretRotation: true` when creating or updating the delegation credential. There is no toggle for this in the Cal.com dashboard yet.

<Note>
  Automatic secret rotation only applies to Microsoft 365 delegation credentials. Google Workspace delegation credentials use a service account key that doesn't expire, so there's no rotation to opt out of.
</Note>

### What happens after opting out

Once a credential has opted out of automatic rotation, Cal.com stops minting and promoting secrets for it. Instead, it sends a reminder: about 14 days before the current secret expires, Cal.com fires a `DELEGATION_CREDENTIAL_ROTATION_REQUIRED` [webhook](/help/webhooks) so you can rotate the secret yourself before the credential stops working. The reminder keeps repeating while the secret is close to expiry or recently expired, and stops once the secret has been expired for more than 30 days.

To act on the reminder:

1. Create a new client secret for the application in the Microsoft Entra admin center (see [Step 3](#step-3-create-a-client-secret) above).
2. Update the delegation credential in Cal.com with the new secret value, either from **Settings → Organization → Delegation Credential** or via the API.

If you opted out, you don't need to grant `Application.ReadWrite.OwnedBy` — Cal.com never attempts to modify the app registration's secrets for an opted-out credential.

***

## Disabling the Delegation Credential

Disabling a Delegation Credential:

* Immediately stops auto-connecting calendars for members who haven't manually connected Microsoft 365
* Preserves existing calendar preferences (selected calendars and destination calendar) for members who had them configured
* Background jobs clean up delegation-specific credential records over time

If you no longer need the underlying app registration, you can also remove the client secret or delete the application in the Microsoft Entra admin center.

***

## Frequently asked questions

<AccordionGroup>
  <Accordion title="Do members need to do anything after the credential is enabled?">
    No. Microsoft 365 Calendar is automatically connected for all members whose email matches the domain. Members can optionally complete [onboarding](/help/enterprise/members-onboarding) to select which calendars to check for conflicts.
  </Accordion>

  <Accordion title="What if a member already connected Microsoft 365 manually?">
    The Delegation Credential takes priority for the matching domain. The member's manual connection is preserved but the delegation-managed credential is used for calendar operations.
  </Accordion>

  <Accordion title="What permissions does the application get?">
    The application is granted up to three Microsoft Graph application permissions:

    * **Calendars.ReadWrite** — read availability and create or update calendar events for members in the configured tenant.
    * **User.Read.All** — resolve the Microsoft 365 user for a Cal.com member by their email address.
    * **Application.ReadWrite.OwnedBy** — rotate the client secret on the app registration Cal.com owns before it expires. Only needed if you use [automatic secret rotation](#client-secret-rotation); skip it if you opt out and rotate secrets manually.

    Cal.com cannot read mail, files, or any other Microsoft 365 data, and `Application.ReadWrite.OwnedBy` is scoped to applications the credential owns — it cannot modify other apps in your tenant.
  </Accordion>

  <Accordion title="What happens when the client secret expires?">
    With `Application.ReadWrite.OwnedBy` granted, Cal.com automatically rotates the client secret before it expires — you do not need to create a new secret manually. If you've [opted out of automatic rotation](#client-secret-rotation), or the permission is not granted (or admin consent is revoked), the credential stops working once the secret expires. Create a new client secret in the Microsoft Entra admin center and update the credential in Cal.com from the Delegation Credential settings.
  </Accordion>

  <Accordion title="Automatic rotation is set up but keeps failing — how do I find out why?">
    `GET /v2/organizations/{orgId}/delegation-credentials/{credentialId}` returns the credential's rotation state, including `secretRotationErrorCode` (for example `missing_permission` or `tenant_lifetime_policy`), whether rotation is blocked, and the active and pending secret dates. [Set up automatic secret rotation](/help/enterprise/delegation-credential-microsoft-365-secret-rotation#when-rotation-fails) explains each code and how to clear a blocked credential.
  </Accordion>

  <Accordion title="Can Conditional Access break secret rotation?">
    Yes. A Conditional Access policy that blocks app-only (`client_credentials`) token requests stops Cal.com from validating a newly created secret, so rotation fails at the promotion stage even though the permissions and ownership look correct.
  </Accordion>

  <Accordion title="Can I turn off automatic secret rotation?">
    Yes. See [Client secret rotation](#client-secret-rotation) above — this is currently only available via the API v2, not the dashboard. Opted-out credentials get a `DELEGATION_CREDENTIAL_ROTATION_REQUIRED` webhook about 14 days before their secret expires, as a reminder to rotate it manually.
  </Accordion>
</AccordionGroup>
