Skip to main content
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)
  • Identity Provider supporting SCIM 2.0
  • SAML database configured

Supported Identity Providers

Cal.com supports SCIM with the following providers:
ProviderSCIM VersionStatus
Azure AD / Entra ID2.0Fully Supported
Okta2.0Fully Supported
JumpCloud2.0Fully Supported
OneLogin2.0Fully Supported
Generic SCIM2.0Fully Supported
Source: packages/features/ee/dsync/lib/directoryProviders.ts:1-23

Setup Guide

1. Prerequisites Configuration

Ensure SSO/SAML is configured first:
.env
# 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=[email protected]

# 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:
// SCIM creates user with attributes
const event = {
  event: "user.created",
  data: {
    email: "[email protected]",
    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:
// SCIM sends update event
const event = {
  event: "user.updated",
  data: {
    email: "[email protected]",
    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:
// SCIM sends deactivation event
const event = {
  event: "user.updated",
  data: {
    email: "[email protected]",
    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:
// SCIM sends deletion event
const event = {
  event: "user.deleted",
  data: {
    email: "[email protected]",
  },
};

// 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:
// Example SCIM payload with custom attributes
{
  "schemas": [
    "urn:ietf:params:scim:schemas:core:2.0:User",
    "custom:enterprise"
  ],
  "userName": "[email protected]",
  "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:
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

// Group creation
const event = {
  event: "group.created",
  data: {
    name: "Engineering",
    members: [
      { value: "[email protected]" },
      { value: "[email protected]" },
    ],
  },
};

// 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:
.env
# 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: [email protected]
[SCIM] User updated: [email protected]
[SCIM] User deactivated: [email protected]
[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

EndpointMethodPurpose
/api/scim/v2.0/UsersGETList users
/api/scim/v2.0/UsersPOSTCreate user
/api/scim/v2.0/Users/{id}GETGet user
/api/scim/v2.0/Users/{id}PUTUpdate user
/api/scim/v2.0/Users/{id}PATCHPartial update user
/api/scim/v2.0/Users/{id}DELETEDelete user
/api/scim/v2.0/GroupsGETList groups
/api/scim/v2.0/GroupsPOSTCreate group
/api/scim/v2.0/Groups/{id}GETGet group
/api/scim/v2.0/Groups/{id}PUTUpdate group
/api/scim/v2.0/Groups/{id}PATCHPartial update group
/api/scim/v2.0/Groups/{id}DELETEDelete group
/api/scim/v2.0/ServiceProviderConfigGETGet SCIM config
/api/scim/v2.0/ResourceTypesGETGet resource types
/api/scim/v2.0/SchemasGETGet schemas

Authentication

All SCIM requests require Bearer token authentication:
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:
// 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

Build docs developers (and LLMs) love