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.
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. |
{
"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.
{
"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.
{
"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.
{
"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.
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "409",
"scimType": "uniqueness",
"detail": "userName already exists"
}ServiceProviderConfig capabilities
ServiceProviderConfigadvertisessort.supported=true,bulk.supported=true, andetag.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=falseandDELETE /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.