---
title: "SCIM API reference"
description: "SCIM 2.0 endpoint contract for provisioning users and groups into XID."
locale: "en"
---

> Documentation Index
> Fetch the locale documentation index at: https://xid.dev/en/llms.txt
> Use this file to discover all available pages before exploring further.

# SCIM API reference

## Base URL

XID exposes organization-scoped SCIM 2.0 APIs under `/scim/v2/organizations/{organization_id}`. User and group resources are addressed with the organization ID in the path.

Configure your identity provider with the base URL `https://xid.dev/scim/v2/organizations/{organization_id}` and the directory token shown once when you create or rotate the directory.

```shell
curl https://xid.dev/scim/v2/organizations/{organization_id}/Users \
  -H 'Authorization: Bearer scim_xxx' \
  -H 'Content-Type: application/scim+json'
```

## Authentication

SCIM calls use a directory bearer token created from the Management API. XID stores only a hash of the token and returns the plaintext token once when it is created or rotated.

| Header | Value | Notes |
| --- | --- | --- |
| `Authorization` | `Bearer scim_xxx` | Required for organization-scoped user and group endpoints. |
| `Content-Type` | `application/scim+json` | Required for POST, PUT, and PATCH requests. |
| `Accept` | `application/scim+json` | Recommended for all SCIM clients. |

## Endpoints

| Endpoint | Methods | Use |
| --- | --- | --- |
| `/scim/v2/ServiceProviderConfig` | `GET` | ServiceProviderConfig response for SCIM client discovery. |
| `/scim/v2/Schemas` | `GET` | User and Group schema metadata. |
| `/scim/v2/ResourceTypes` | `GET` | Supported SCIM resource types. |
| `/scim/v2/organizations/{organization_id}/Users` | `GET, POST` | Create and list directory users. |
| `/scim/v2/organizations/{organization_id}/Users/{id}` | `GET, PUT, PATCH, DELETE` | Read, replace, patch, or deprovision one directory user. |
| `/scim/v2/organizations/{organization_id}/Groups` | `GET, POST` | Create and list directory groups. |
| `/scim/v2/organizations/{organization_id}/Groups/{id}` | `GET, PUT, PATCH, DELETE` | Read, replace, patch, or remove one directory group. |

## User resource

User resources use `userName` as the external identifier. Email values, profile name fields, active state, and enterprise extension fields are preserved in the SCIM raw profile.

| SCIM field | XID behavior |
| --- | --- |
| `id` | Stable XID directory user ID. |
| `userName` | Required. Must be unique inside the directory. |
| `active` | `false` deprovisions the user and revokes active sessions. |
| `emails` | Primary email is used for matching and account linking. |
| `urn:ietf:params:scim:schemas:extension:enterprise:2.0:User` | Stored and returned for enterprise attributes such as department. |

```json
{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "userName": "alice@example.com",
  "active": true,
  "name": { "givenName": "Alice", "familyName": "Lee" },
  "emails": [{ "value": "alice@example.com", "primary": true }]
}
```

## Group resource

Group resources use `displayName` as the unique directory group name. Members reference SCIM user IDs and are synchronized idempotently.

```json
{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
  "displayName": "Engineering",
  "members": [
{ "value": "dir_user_123", "display": "alice@example.com" }
  ]
}
```

## Filtering, sorting, and pagination

XID supports SCIM filter grammar with `and`, `or`, `not`, and comparison operators (`eq`, `ne`, `co`, `sw`, `ew`, `gt`, `ge`, `lt`, `le`, `pr`). Unsupported expressions return `invalidFilter`. List responses use SCIM 1-based pagination with `startIndex`, `count`, and `totalResults`, plus optional `sortBy` and `sortOrder`.

| Query | Support |
| --- | --- |
| `filter=userName eq "alice@example.com"` | Find one user by userName. |
| `filter=displayName eq "Engineering"` | Find one group by displayName. |
| `filter=userName sw "alice" and active eq true` | Combine logical and comparison operators. |
| `sortBy=userName&sortOrder=ascending` | Sort Users or Groups list results. |
| `startIndex=1&count=100` | Return up to 100 resources from the first result. |
| `attributes=userName,emails.value` | Return only schemas, id, and the requested SCIM attributes. |
| `excludedAttributes=emails,meta` | Return the default resource without the excluded SCIM attributes. |

## Bulk operations

`POST /scim/v2/organizations/{organization_id}/Bulk` accepts a `BulkRequest` with up to 100 operations and a 1 MiB payload limit. Responses return per-operation HTTP status in a `BulkResponse` even when some operations fail.

```json
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkRequest"],
  "Operations": [
{
  "method": "POST",
  "path": "/Users",
  "bulkId": "user1",
  "data": { "userName": "alice@example.com", "active": true }
}
  ]
}
```

## ETag and If-Match

Resource GET responses include `ETag: W/"<meta.version>"` from `meta.version`. `PUT` and `PATCH` require an `If-Match` header matching the current version; missing headers return `428` and mismatches return `412`.

## PATCH operations

PATCH requests use `urn:ietf:params:scim:api:messages:2.0:PatchOp`. XID supports `add`, `replace`, and `remove` for writable profile fields and group memberships.

```json
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
{ "op": "replace", "path": "active", "value": false }
  ]
}
```

## Error responses

SCIM errors return `application/scim+json` with the SCIM Error schema, HTTP status, detail, and optional `scimType`.

```json
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
  "status": "409",
  "scimType": "uniqueness",
  "detail": "userName already exists"
}
```

## ServiceProviderConfig capabilities

- `ServiceProviderConfig` advertises `sort.supported=true`, `bulk.supported=true`, and `etag.supported=true`.
- XID exposes inbound SCIM Service Provider endpoints for external IdPs. Downstream SaaS SCIM push clients have local fake-SaaS evidence, but production support still requires real SaaS admin L4.

## Deprovisioning behavior

- Directory token rotation keeps the previous token valid for a short grace window.
- `active=false` and `DELETE /Users/{id}` deprovision the user and revoke active sessions.
- Group membership updates are idempotent. Unknown members can be resolved after the user arrives from the identity provider.

Source: https://xid.dev/scim/index.mdx
