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

# SCIM Provisioning

> Automate user lifecycle management with SCIM 2.0

System for Cross-domain Identity Management (SCIM) 2.0 enables automated user provisioning and deprovisioning between your identity provider and Cal.com. SCIM works alongside SSO to provide complete identity lifecycle management.

## Overview

SCIM provides:

* **Automated User Provisioning**: Automatically create users when added to IdP
* **Deprovisioning**: Remove access when users leave the organization
* **Attribute Sync**: Keep user profiles synchronized with IdP
* **Group Management**: Map IdP groups to Cal.com teams
* **Real-time Updates**: Changes in IdP reflect immediately in Cal.com

## Prerequisites

* Cal.com Enterprise license
* Organizations feature enabled
* SSO/SAML configured (see [SAML Setup](/enterprise/saml))
* Identity Provider supporting SCIM 2.0
* SAML database configured

## Supported Identity Providers

Cal.com supports SCIM with the following providers:

| Provider                | SCIM Version | Status          |
| ----------------------- | ------------ | --------------- |
| **Azure AD / Entra ID** | 2.0          | Fully Supported |
| **Okta**                | 2.0          | Fully Supported |
| **JumpCloud**           | 2.0          | Fully Supported |
| **OneLogin**            | 2.0          | Fully Supported |
| **Generic SCIM**        | 2.0          | Fully Supported |

Source: `packages/features/ee/dsync/lib/directoryProviders.ts:1-23`

## Setup Guide

### 1. Prerequisites Configuration

Ensure SSO/SAML is configured first:

```bash .env theme={null}
# Required: SAML database (shared with SCIM)
SAML_DATABASE_URL=postgresql://postgres:@localhost:5450/cal-saml

# Required: Encryption key
CALENDSO_ENCRYPTION_KEY=your_encryption_key

# Required: SAML admins
SAML_ADMINS=admin@company.com

# Optional: Enable SCIM request logging for specific directories
DIRECTORY_IDS_TO_LOG=dir_123,dir_456
```

Source: `.env.example:455-456`

### 2. SCIM Endpoint Configuration

Cal.com exposes SCIM endpoints at:

```
Base URL: https://your-domain.com/api/scim/v2.0
```

**Available Endpoints:**

* `/Users` - User management
* `/Groups` - Group/team management
* `/ServiceProviderConfig` - SCIM configuration
* `/ResourceTypes` - Supported resource types
* `/Schemas` - SCIM schema definitions

Source: `packages/features/ee/sso/lib/jackson.ts:24`

### 3. Generate SCIM Token

1. Log in to Cal.com as a SAML admin
2. Navigate to Settings → Security → Directory Sync
3. Select your organization
4. Click "Create Directory"
5. Choose your identity provider
6. Copy the generated SCIM token and endpoint URL

### 4. Configure Identity Provider

#### Azure AD / Entra ID

1. Navigate to your Enterprise Application
2. Select Provisioning → Automatic
3. Configure:
   * **Tenant URL**: `https://your-domain.com/api/scim/v2.0`
   * **Secret Token**: \[SCIM token from step 3]
4. Click "Test Connection"
5. Configure Attribute Mappings:
   ```
   userPrincipalName → userName
   mail              → emails[type eq "work"].value
   givenName         → name.givenName
   surname           → name.familyName
   displayName       → displayName
   ```
6. Set Provisioning Status to "On"
7. Save and perform initial sync

#### Okta

1. Navigate to Applications → Your SAML App
2. Go to Provisioning tab → Configure API Integration
3. Enable API integration
4. Configure:
   * **Base URL**: `https://your-domain.com/api/scim/v2.0`
   * **API Token**: \[SCIM token from step 3]
5. Test API Credentials
6. Enable provisioning features:
   * ✅ Create Users
   * ✅ Update User Attributes
   * ✅ Deactivate Users
   * ✅ Sync Password (optional)
7. Configure Attribute Mappings:
   ```
   userName      → email
   email         → email
   givenName     → firstName
   familyName    → lastName
   ```
8. Save and assign users to application

#### JumpCloud

1. Navigate to SSO Applications → Your Cal.com App
2. Enable Identity Management
3. Configure:
   * **SCIM Version**: 2.0
   * **Base URL**: `https://your-domain.com/api/scim/v2.0`
   * **Token Key**: `Authorization`
   * **Token Value**: `Bearer [SCIM token]`
4. Configure Attribute Mappings:
   ```
   email         → email
   firstname     → name.givenName
   lastname      → name.familyName
   username      → userName
   ```
5. Activate provisioning

#### OneLogin

1. Navigate to Applications → Your SAML App
2. Go to Provisioning tab
3. Enable Provisioning
4. Configure:
   * **SCIM Base URL**: `https://your-domain.com/api/scim/v2.0`
   * **SCIM Bearer Token**: \[SCIM token from step 3]
5. Enable:
   * ✅ Enable provisioning
   * ✅ Create user
   * ✅ Delete user
   * ✅ Update user
6. Configure Field Mappings
7. Save and run provisioning

## User Lifecycle Management

### User Creation

When a user is assigned to the Cal.com app in your IdP:

```typescript theme={null}
// SCIM creates user with attributes
const event = {
  event: "user.created",
  data: {
    email: "user@company.com",
    firstName: "John",
    lastName: "Doe",
    active: true,
  },
};

// Cal.com processes:
1. Check if user exists in database
2. If not, create new user with SAML identity provider
3. Connect user to organization based on email domain
4. Send invitation email
5. Sync custom attributes from SCIM payload
```

Source: `packages/features/ee/dsync/lib/handleUserEvents.ts:124-150`

### User Updates

When user attributes change in IdP:

```typescript theme={null}
// SCIM sends update event
const event = {
  event: "user.updated",
  data: {
    email: "user@company.com",
    firstName: "Jane", // Changed
    active: true,
  },
};

// Cal.com processes:
1. Find user by email
2. Update user attributes
3. Sync custom attributes to user profile
4. If user is member, sync attributes to organization
```

Source: `packages/features/ee/dsync/lib/handleUserEvents.ts:59-115`

### User Deactivation

When a user is unassigned or deactivated in IdP:

```typescript theme={null}
// SCIM sends deactivation event
const event = {
  event: "user.updated",
  data: {
    email: "user@company.com",
    active: false, // Deactivated
  },
};

// Cal.com processes:
1. Find user by email
2. Remove user from organization
3. Revoke organization membership
4. Cancel pending workflows and bookings (optional)
5. User retains account but loses org access
```

Source: `packages/features/ee/dsync/lib/handleUserEvents.ts:116-122`

### User Deletion

When a user is permanently deleted from IdP:

```typescript theme={null}
// SCIM sends deletion event
const event = {
  event: "user.deleted",
  data: {
    email: "user@company.com",
  },
};

// Cal.com processes:
1. Find user by email
2. Remove from organization
3. User account remains (can be deleted manually)
```

Source: `packages/features/ee/dsync/lib/removeUserFromOrg.ts`

## Custom Attribute Synchronization

SCIM can sync custom attributes beyond standard fields:

### SCIM Schema

Cal.com uses the standard SCIM 2.0 User schema:

```
Core Schema URN: urn:ietf:params:scim:schemas:core:2.0:User
```

Source: `packages/features/ee/dsync/lib/getAttributesFromScimPayload.ts:11`

### Custom Attributes

Extract custom attributes from SCIM payload:

```typescript theme={null}
// Example SCIM payload with custom attributes
{
  "schemas": [
    "urn:ietf:params:scim:schemas:core:2.0:User",
    "custom:enterprise"
  ],
  "userName": "user@company.com",
  "custom:enterprise": {
    "department": "Engineering",
    "employeeNumber": "12345",
    "costCenter": "R&D"
  }
}

// Cal.com extracts and stores:
const customAttributes = {
  department: "Engineering",
  employeeNumber: "12345",
  costCenter: "R&D"
};
```

Source: `packages/features/ee/dsync/lib/getAttributesFromScimPayload.ts:35-120`

### Attribute Assignment

Custom attributes are assigned to users in the organization context:

```typescript theme={null}
await assignValueToUserInOrgBulk({
  orgId: organization.id,
  userId: user.id,
  attributeLabelToValueMap: customAttributes,
  updater: {
    dsyncId: directoryId, // Tracks SCIM as source
  },
});
```

Source: `packages/features/ee/dsync/lib/handleUserEvents.ts:49-56`

### Attribute Pools

Cal.com maintains separate pools for attribute assignments:

1. **SCIM Pool**: Attributes managed by SCIM directory
2. **Cal.com User Pool**: Attributes managed by Cal.com users

**Rules:**

* SCIM updates only affect SCIM pool attributes
* Cal.com users can override SCIM attributes (moves to User Pool)
* Multiple SCIM directories can coexist
* Deleting SCIM directory only removes its pool attributes

Source: `packages/features/ee/dsync/lib/assignValueToUserUtils.ts:14-35`

## Group Management

SCIM can map IdP groups to Cal.com teams:

### Group Events

```typescript theme={null}
// Group creation
const event = {
  event: "group.created",
  data: {
    name: "Engineering",
    members: [
      { value: "user1@company.com" },
      { value: "user2@company.com" },
    ],
  },
};

// Cal.com processes:
1. Create or map to existing team
2. Add group members to team
3. Set appropriate permissions
```

Source: `packages/features/ee/dsync/lib/handleGroupEvents.ts`

### Team Mapping

Groups from IdP are automatically mapped to teams:

* Group display name → Team name
* Group members → Team members
* Nested groups supported (if IdP supports)

## Monitoring and Debugging

### Enable SCIM Logging

Log SCIM requests for specific directories:

```bash .env theme={null}
# Comma-separated list of directory IDs to log
DIRECTORY_IDS_TO_LOG=dir_abc123,dir_xyz789
```

Source: `.env.example:455-456`

### Check Provisioning Status

1. Log in as SAML admin
2. Navigate to Settings → Security → Directory Sync
3. View sync status and logs:
   * Last sync time
   * Users provisioned
   * Errors and warnings
   * Pending operations

### Common Log Entries

```
[SCIM] User created: user@company.com
[SCIM] User updated: user@company.com
[SCIM] User deactivated: user@company.com
[SCIM] Custom attributes synced: department, role
[SCIM] Group created: Engineering
```

## Troubleshooting

### SCIM Connection Test Fails

**Solutions:**

1. Verify SCIM endpoint URL is correct
2. Check SCIM token is valid and not expired
3. Ensure `SAML_DATABASE_URL` is configured
4. Verify network connectivity to Cal.com
5. Check firewall rules allow IdP to reach endpoint

### Users Not Provisioning

**Solutions:**

1. Verify users are assigned to the application in IdP
2. Check attribute mappings are correct
3. Ensure email format is valid
4. Verify organization auto-linking is configured
5. Check user doesn't already belong to another organization

Source: `packages/features/ee/dsync/lib/handleUserEvents.ts:81-83`

### Custom Attributes Not Syncing

**Solutions:**

1. Verify custom schema is included in SCIM payload
2. Check attribute names match expected format
3. Ensure custom attributes are mapped in IdP
4. Review SCIM request logs with `DIRECTORY_IDS_TO_LOG`

Source: `packages/features/ee/dsync/lib/getAttributesFromScimPayload.ts`

### Group Mapping Issues

**Solutions:**

1. Verify groups are assigned to application in IdP
2. Check group provisioning is enabled
3. Ensure group members have valid email addresses
4. Verify team creation permissions in Cal.com

Source: `packages/features/ee/dsync/lib/handleGroupEvents.ts`

### User Belongs to Another Organization

**Error**: "User belongs to another organization."

**Solution**: Users can only belong to one organization at a time. To migrate:

1. Remove user from current organization
2. Re-provision through SCIM

Source: `packages/features/ee/dsync/lib/handleUserEvents.ts:81-83`

### Permission Denied Errors

**Solutions:**

1. Verify you're logged in as SAML admin
2. Check email is in `SAML_ADMINS` environment variable
3. For hosted deployments, verify organization Owner/Admin role
4. Ensure SCIM token has correct permissions

## Security Best Practices

1. **Rotate Tokens**: Regularly rotate SCIM bearer tokens
2. **Limit Scope**: Use minimum required permissions for SCIM token
3. **Monitor Logs**: Review provisioning logs for suspicious activity
4. **Enable HTTPS**: Always use HTTPS for SCIM endpoints
5. **Validate Requests**: Cal.com validates all SCIM requests against schema
6. **Audit Events**: Track user provisioning and deprovisioning events
7. **Secure Database**: Ensure SAML database has proper access controls

## Performance Considerations

### Initial Sync

First-time provisioning may take time for large organizations:

* **\< 100 users**: Few minutes
* **100-1000 users**: 10-30 minutes
* **> 1000 users**: May require batching

### Ongoing Sync

Real-time updates typically process within seconds:

* User creation: 1-3 seconds
* User update: \< 1 second
* User deactivation: 1-2 seconds
* Group operations: 2-5 seconds

### Rate Limiting

Cal.com implements rate limiting on SCIM endpoints to prevent abuse. If you encounter rate limits:

1. Reduce sync frequency in IdP
2. Batch operations where possible
3. Contact support for rate limit increases

## API Reference

### SCIM Endpoints

| Endpoint                               | Method | Purpose              |
| -------------------------------------- | ------ | -------------------- |
| `/api/scim/v2.0/Users`                 | GET    | List users           |
| `/api/scim/v2.0/Users`                 | POST   | Create user          |
| `/api/scim/v2.0/Users/{id}`            | GET    | Get user             |
| `/api/scim/v2.0/Users/{id}`            | PUT    | Update user          |
| `/api/scim/v2.0/Users/{id}`            | PATCH  | Partial update user  |
| `/api/scim/v2.0/Users/{id}`            | DELETE | Delete user          |
| `/api/scim/v2.0/Groups`                | GET    | List groups          |
| `/api/scim/v2.0/Groups`                | POST   | Create group         |
| `/api/scim/v2.0/Groups/{id}`           | GET    | Get group            |
| `/api/scim/v2.0/Groups/{id}`           | PUT    | Update group         |
| `/api/scim/v2.0/Groups/{id}`           | PATCH  | Partial update group |
| `/api/scim/v2.0/Groups/{id}`           | DELETE | Delete group         |
| `/api/scim/v2.0/ServiceProviderConfig` | GET    | Get SCIM config      |
| `/api/scim/v2.0/ResourceTypes`         | GET    | Get resource types   |
| `/api/scim/v2.0/Schemas`               | GET    | Get schemas          |

### Authentication

All SCIM requests require Bearer token authentication:

```bash theme={null}
Authorization: Bearer <scim_token>
```

## Advanced Configuration

### Multiple SCIM Directories

Organizations can configure multiple SCIM directories:

```
Directory 1: Azure AD → HR Department
Directory 2: Okta → Engineering Department
Directory 3: JumpCloud → Sales Department
```

Each directory maintains its own attribute pool, allowing different sources of truth for different user groups.

Source: `packages/features/ee/dsync/lib/assignValueToUserUtils.ts:14-35`

### Custom Attribute Mapping

Map IdP-specific attributes to Cal.com fields:

```typescript theme={null}
// Example: Map department to team assignment
if (customAttributes.department === "Engineering") {
  assignToTeam(user, engineeringTeam);
} else if (customAttributes.department === "Sales") {
  assignToTeam(user, salesTeam);
}
```

## Testing SCIM Integration

### 1. Test User Creation

1. Assign a test user to the application in your IdP
2. Wait for provisioning to complete
3. Verify user appears in Cal.com
4. Check user has correct attributes

### 2. Test User Update

1. Update user attributes in IdP (e.g., name)
2. Wait for sync
3. Verify changes reflect in Cal.com

### 3. Test User Deactivation

1. Unassign user from application in IdP
2. Wait for deprovisioning
3. Verify user loses organization access
4. Confirm user account still exists

### 4. Test Group Provisioning

1. Create a group in IdP
2. Assign users to group
3. Assign group to Cal.com application
4. Verify team is created in Cal.com
5. Confirm group members are team members

## Related Documentation

* [SSO Configuration](/enterprise/sso)
* [SAML Setup](/enterprise/saml)
* [Organizations Management](/enterprise/organizations)
* [SCIM 2.0 Specification](https://scim.cloud/)
* [BoxyHQ Directory Sync](https://boxyhq.com/docs/directory-sync/overview)
