Summary and recommendation
The Databricks SCIM 2.0 API is the correct integration surface for programmatic user lifecycle management. Account-level endpoints (`/api/2.0/accounts/{account_id}/scim/v2/Users`) are the recommended path; workspace-level SCIM (`/api/2.0/preview/scim/v2/Users`) is legacy and should not be used for new integrations.
Authentication supports Bearer tokens via Personal Access Token or OAuth 2.0 M2M client credentials. OAuth M2M is preferred for service-to-service integrations: POST to the OIDC token endpoint with `grant_type=client_credentials` and `scope=all-apis`, then pass the token as `Authorization: Bearer {token}`. Account-level operations require an account admin role; workspace-level operations require workspace admin.
Pagination follows SCIM conventions: `startIndex` is 1-based (not 0-based), default page size is 100, maximum is 10,000. Rate limits are not publicly documented; HTTP 429 is returned when exceeded, and exponential backoff is required. Use `Content-Type: application/scim+json` on all SCIM requests - `application/json` may cause parsing failures.
API quick reference
| Has user API | Yes |
| Auth method | Bearer token (Personal Access Token or OAuth 2.0 M2M client credentials) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Premium (formerly Pro; Standard tier being phased out — AWS/GCP by Oct 2025, Azure Standard by Oct 2026) |
Authentication
Auth method: Bearer token (Personal Access Token or OAuth 2.0 M2M client credentials)
Setup steps
- For PAT: Navigate to Databricks workspace → User Settings → Developer → Access Tokens → Generate new token.
- For OAuth M2M: Register a Service Principal in the Databricks account console, generate a client ID and secret.
- For OAuth M2M token exchange: POST to https://accounts.cloud.databricks.com/oidc/accounts/{account_id}/v1/token with grant_type=client_credentials and scope=all-apis.
- Pass the token in the Authorization header as 'Bearer {token}' on all API requests.
- Account-level operations require an account admin role; workspace-level operations require workspace admin.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| all-apis | Full access to all Databricks REST APIs including user management | OAuth M2M service principal access to account and workspace APIs |
| accounts | Access to account-level management APIs | Account-level user and group CRUD via OAuth M2M |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Databricks-assigned unique user ID | server-assigned | immutable | Used as path parameter for GET/PATCH/DELETE |
| userName | string | Primary email address / login identifier | required | allowed | Must be unique within the account; case-insensitive |
| displayName | string | Full display name of the user | optional | allowed | Derived from name.givenName + name.familyName if not set |
| name.givenName | string | First name | optional | allowed | SCIM sub-attribute under name object |
| name.familyName | string | Last name | optional | allowed | SCIM sub-attribute under name object |
| emails | array | List of email objects with value and primary flag | optional | allowed | Primary email should match userName |
| active | boolean | Whether the user account is active | optional (defaults true) | allowed | Setting to false deactivates the user without deleting; preferred over DELETE for deprovisioning |
| groups | array | Groups the user belongs to (read-only on user object) | server-assigned | manage via Groups API | Read-only; modify group membership through the Groups endpoint |
| roles | array | Account-level roles assigned to the user (e.g., account_admin) | optional | allowed | Values: account_admin. Workspace roles managed separately via workspace permissions |
| entitlements | array | Workspace-level entitlements (e.g., allow-cluster-create, allow-instance-pool-create) | optional | allowed | Workspace-level API only; not present on account-level user object |
| externalId | string | Identifier from the external IdP (set by SCIM provisioner) | optional | allowed | Used by IdPs like Okta/Entra to correlate records; not used for auth |
| schemas | array | SCIM schema URNs | required for SCIM | required for SCIM | Must include urn:ietf:params:scim:schemas:core:2.0:User |
Core endpoints
List users (account-level)
- Method: GET
- URL:
https://accounts.cloud.databricks.com/api/2.0/accounts/{account_id}/scim/v2/Users - Watch out for: startIndex is 1-based (SCIM standard), not 0-based. Filter syntax follows SCIM filter spec.
Request example
GET /api/2.0/accounts/{account_id}/scim/v2/Users?filter=userName+eq+%22user@example.com%22&count=100&startIndex=1
Authorization: Bearer {token}
Response example
{
"totalResults": 1,
"startIndex": 1,
"itemsPerPage": 1,
"Resources": [{
"id": "1234567890",
"userName": "user@example.com",
"active": true
}]
}
Get user by ID (account-level)
- Method: GET
- URL:
https://accounts.cloud.databricks.com/api/2.0/accounts/{account_id}/scim/v2/Users/{id} - Watch out for: Account-level and workspace-level user IDs are different; do not interchange them.
Request example
GET /api/2.0/accounts/{account_id}/scim/v2/Users/1234567890
Authorization: Bearer {token}
Response example
{
"id": "1234567890",
"userName": "user@example.com",
"displayName": "Jane Doe",
"active": true,
"roles": [{"value": "account_admin"}]
}
Create user (account-level)
- Method: POST
- URL:
https://accounts.cloud.databricks.com/api/2.0/accounts/{account_id}/scim/v2/Users - Watch out for: Creating a user at account level does not automatically grant workspace access; assign to workspace separately.
Request example
POST /api/2.0/accounts/{account_id}/scim/v2/Users
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "newuser@example.com",
"displayName": "New User",
"active": true
}
Response example
{
"id": "9876543210",
"userName": "newuser@example.com",
"displayName": "New User",
"active": true
}
Update user (partial, account-level)
- Method: PATCH
- URL:
https://accounts.cloud.databricks.com/api/2.0/accounts/{account_id}/scim/v2/Users/{id} - Watch out for: Use PATCH with active=false to deactivate rather than DELETE to preserve audit history and allow reactivation.
Request example
PATCH /api/2.0/accounts/{account_id}/scim/v2/Users/1234567890
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [{"op": "replace", "path": "active", "value": false}]
}
Response example
HTTP 200
{
"id": "1234567890",
"userName": "user@example.com",
"active": false
}
Replace user (full update, account-level)
- Method: PUT
- URL:
https://accounts.cloud.databricks.com/api/2.0/accounts/{account_id}/scim/v2/Users/{id} - Watch out for: PUT replaces the entire user object; omitted fields may be cleared. Prefer PATCH for partial updates.
Request example
PUT /api/2.0/accounts/{account_id}/scim/v2/Users/1234567890
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "user@example.com",
"displayName": "Jane Updated",
"active": true
}
Response example
HTTP 200
{
"id": "1234567890",
"userName": "user@example.com",
"displayName": "Jane Updated",
"active": true
}
Delete user (account-level)
- Method: DELETE
- URL:
https://accounts.cloud.databricks.com/api/2.0/accounts/{account_id}/scim/v2/Users/{id} - Watch out for: DELETE permanently removes the user from the account. Databricks recommends deactivating (active=false) instead to preserve audit trails.
Request example
DELETE /api/2.0/accounts/{account_id}/scim/v2/Users/1234567890
Authorization: Bearer {token}
Response example
HTTP 204 No Content
List workspace users
- Method: GET
- URL:
https://{workspace_host}/api/2.0/preview/scim/v2/Users - Watch out for: Workspace-level SCIM is legacy; Databricks recommends account-level SCIM. Workspace users must first exist at account level.
Request example
GET https://{workspace_host}/api/2.0/preview/scim/v2/Users?count=50&startIndex=1
Authorization: Bearer {token}
Response example
{
"totalResults": 200,
"startIndex": 1,
"itemsPerPage": 50,
"Resources": [{"id": "...", "userName": "user@example.com"}]
}
Assign user to workspace
- Method: POST
- URL:
https://accounts.cloud.databricks.com/api/2.0/accounts/{account_id}/workspaces/{workspace_id}/permissionassignments - Watch out for: principal_id is the numeric account-level user ID. Permissions values: USER or ADMIN.
Request example
POST /api/2.0/accounts/{account_id}/workspaces/{workspace_id}/permissionassignments
{
"principal_id": 1234567890,
"permissions": ["USER"]
}
Response example
HTTP 200
{
"permission_assignment": {
"principal": {"user_id": 1234567890},
"permissions": ["USER"]
}
}
Rate limits, pagination, and events
- Rate limits: Databricks does not publish explicit per-endpoint rate limits in official documentation. Limits are enforced at the platform level and vary by workspace/account tier.
- Rate-limit headers: No
- Retry-After header: No
- Rate-limit notes: HTTP 429 Too Many Requests is returned when limits are exceeded. Databricks recommends exponential backoff. SCIM provisioning calls from IdPs are subject to the same undocumented limits.
- Pagination method: token
- Default page size: 100
- Max page size: 10000
- Pagination pointer: startIndex (1-based, SCIM-style) + count; response includes totalResults, startIndex, itemsPerPage
| Plan | Limit | Concurrent |
|---|---|---|
| Premium | Not publicly documented; platform-enforced | 0 |
- Webhooks available: No
- Webhook notes: Databricks does not offer native webhooks for user management events (user created, deactivated, etc.).
- Alternative event strategy: Use Databricks Audit Logs (delivered to cloud storage or Event Hub/Pub Sub) to monitor user lifecycle events. System Tables (audit log table in Unity Catalog) provide queryable audit data on Premium plans.
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Premium (formerly Pro; Standard tier being phased out - AWS/GCP by Oct 2025, Azure Standard by Oct 2026)
Endpoint: https://accounts.cloud.databricks.com/api/2.0/accounts/{account_id}/scim/v2 (account-level, recommended) | https://{workspace_host}/api/2.0/preview/scim/v2 (workspace-level, legacy)
Supported operations: GET /Users (list with filter/pagination), GET /Users/{id}, POST /Users (create), PUT /Users/{id} (full replace), PATCH /Users/{id} (partial update via PatchOp), DELETE /Users/{id}, GET /Groups, POST /Groups, PATCH /Groups/{id}, DELETE /Groups/{id}, GET /ServicePrincipals, POST /ServicePrincipals
Limitations:
- SSO must be configured before enabling SCIM provisioning.
- Account-level SCIM token must be generated by an account admin (not a workspace PAT).
- Workspace-level SCIM is legacy; account-level is recommended for new integrations.
- Deleting a user via SCIM removes them from the account permanently; deactivation is preferred.
- Group nesting (groups within groups) is not supported.
- SCIM provisioning does not automatically assign users to specific workspaces; workspace assignment is a separate step.
- Only one SCIM token is active per account at a time; rotating the token invalidates the previous one.
- externalId set by IdP is stored but not used for authentication.
Common scenarios
Provisioning a new user is a two-call sequence: POST to account-level SCIM to create the user and capture the returned id, then POST to /api/2. 0/accounts/{account_id}/workspaces/{workspace_id}/permissionassignments with principal_id and permissions=["USER"].
The account-level user ID and workspace-level user ID are different values - retrieve the workspace-level ID by querying the workspace SCIM endpoint after assignment before attempting entitlement patches.
For offboarding, prefer PATCH with active=false over DELETE. Deactivation is immediate and revokes all workspace access, but preserves the user record, audit history, and owned objects. DELETE is irreversible, removes the user from all workspaces and the account, and leaves owned jobs and Unity Catalog objects orphaned without automatic reassignment.
For IdP-driven sync (e.g., Okta), generate the SCIM token in Account Console → Identity & Access → SCIM provisioning. Only one SCIM token is valid per account at a time - rotating it immediately breaks any active IdP connection. Update the token in the IdP immediately after rotation. Group nesting is unsupported; only flat group membership is provisioned via SCIM.
Provision a new user via SCIM and assign to a workspace
- POST to /api/2.0/accounts/{account_id}/scim/v2/Users with userName, displayName, active=true to create the account-level user.
- Note the returned id (account-level user ID).
- POST to /api/2.0/accounts/{account_id}/workspaces/{workspace_id}/permissionassignments with principal_id={id} and permissions=["USER"] to grant workspace access.
- Optionally PATCH the workspace-level user to add entitlements (allow-cluster-create) via /api/2.0/preview/scim/v2/Users/{workspace_user_id}.
Watch out for: The account-level user ID and workspace-level user ID are different values. Retrieve the workspace-level ID by querying the workspace SCIM endpoint after assignment.
Deprovision a user (offboarding)
- Look up the user by userName: GET /api/2.0/accounts/{account_id}/scim/v2/Users?filter=userName+eq+%22user@example.com%22.
- PATCH /api/2.0/accounts/{account_id}/scim/v2/Users/{id} with Operations: [{op: replace, path: active, value: false}] to deactivate.
- Deactivated users lose access immediately but their data and audit records are preserved.
- If permanent removal is required, DELETE /api/2.0/accounts/{account_id}/scim/v2/Users/{id}.
Watch out for: DELETE is irreversible and removes the user from all workspaces and the account. Prefer deactivation for compliance and audit purposes.
Configure Okta SCIM provisioning for automated sync
- In Databricks account console: Settings → Identity & Access → SCIM provisioning → Generate token. Copy the token and the SCIM URL (https://accounts.cloud.databricks.com/api/2.0/accounts/{account_id}/scim/v2).
- In Okta: Add the Databricks SCIM app, set Base URL to the SCIM URL, set API Token to the copied token.
- Enable provisioning features: Push Users, Push Groups, Import Users.
- Assign Okta groups/users to the Databricks app to trigger initial sync.
- Test by creating a user in Okta and verifying they appear in the Databricks account console.
Watch out for: Rotating the SCIM token in Databricks immediately invalidates the Okta connection; update the token in Okta immediately after rotation to avoid provisioning failures.
Why building this yourself is a trap
The identity graph in Databricks is split across two namespaces: account-level identities and workspace-level identities share the same userName but carry different numeric IDs. Any integration that conflates these IDs will silently fail on workspace assignment or entitlement operations without a clear error indicating the mismatch.
SCIM provisioning does not automatically assign users to workspaces - this is the most common integration gap. A user created via SCIM appears in the account console but has zero workspace access until the Permission Assignments API is called explicitly.
Automations that treat SCIM POST success as "user is ready" will produce accounts that exist but cannot authenticate to any workspace.
Webhooks for user lifecycle events are not available. Detecting provisioning state changes requires polling the SCIM Users endpoint or querying the audit log system table (system.access.audit) on Premium, which adds latency and query cost to any real-time access verification workflow.
Automate Databricks workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.