Skip to main content

SCIM API reference

Need help?

This page is a reference for the Ory Network SCIM server API. It describes the base URL and authentication, every available endpoint with example requests and responses, the supported resource schemas, pagination and filtering, and the error model.

For a conceptual overview, how SCIM relates to organizations, auto-linking, and data mapping, see the SCIM overview.

The Ory Network SCIM server implements SCIM 2.0 as defined in RFC 7643 (schemas) and RFC 7644 (protocol), with cursor-based pagination from RFC 9865.

Base URL

Each SCIM client has its own base URL. The client ID you choose when configuring the SCIM client is part of the URL:

https://<project-slug>.projects.oryapis.com/scim/<client-id>/v2

The exact URL is shown in the Ory Console when you create or edit a SCIM client. All endpoint paths below are relative to this base URL — for example, POST /Users means POST https://<project-slug>.projects.oryapis.com/scim/<client-id>/v2/Users.

The server returns Content-Type: application/scim+json on every response. Send the same content type on requests that have a body.

Authentication

Every request must include an Authorization header that matches the Authorization header secret configured on the SCIM client. The server compares the header against the configured secret using a constant-time comparison.

Authorization: Bearer <your-secret>

When comparing, the server trims surrounding whitespace and strips a single leading, case-insensitive Bearer prefix. This means that if your configured secret is s3cr3t, both of the following are accepted:

  • Authorization: Bearer s3cr3t
  • Authorization: s3cr3t
info

Some identity providers (for example Microsoft Entra) ask you to enter the token without the Bearer prefix and add it themselves. Because only one Bearer prefix is stripped, configure the secret without a Bearer prefix to avoid double-prefixing. See the provider guides for provider-specific instructions.

Authentication errors:

ConditionStatusdetail
No Authorization header401no authorization header found
Header does not match the secret401invalid authorization header
note

ServiceProviderConfig advertises oauthbearertoken as the authentication scheme — a bearer token in the Authorization header. The token is the SCIM client's configured Authorization header secret, which is a static shared secret rather than an OAuth-issued token.

Service discovery

These read-only endpoints let SCIM clients and conformance tools discover the server's capabilities. They do not require a resource ID.

MethodPathDescription
GET/ServiceProviderConfigServer capabilities (patch, filter, pagination, auth)
GET/ResourceTypesList of supported resource types (User, Group)
GET/ResourceTypes/{id}A single resource type, where id is User or Group
GET/SchemasList of supported schemas (User, Group, Enterprise User)
GET/Schemas/{id}A single schema, where id is the schema URN

GET /ServiceProviderConfig

{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"],
"documentationUri": "https://www.ory.com/docs/kratos/manage-identities/scim",
"patch": { "supported": true },
"bulk": { "supported": false },
"filter": { "supported": true, "maxResults": 1000 },
"changePassword": { "supported": true },
"sort": { "supported": false },
"etag": { "supported": false },
"pagination": {
"cursor": true,
"index": true,
"defaultPaginationMethod": "index",
"defaultPageSize": 100,
"maxPageSize": 1000,
"cursorTimeout": 3600
},
"authenticationSchemes": [
{
"type": "oauthbearertoken",
"name": "OAuth Bearer Token",
"description": "Authentication using a bearer token in the Authorization HTTP header.",
"specUri": "https://datatracker.ietf.org/doc/html/rfc6750",
"documentationUri": "https://www.ory.com/docs/kratos/manage-identities/scim#configure-a-scim-client"
}
],
"meta": { "resourceType": "ServiceProviderConfig" }
}

Users

MethodPathDescriptionSuccess status
GET/UsersList or search users200
POST/UsersCreate a user201
GET/Users/{id}Retrieve a user by ID200
PUT/Users/{id}Replace a user (full update)200
PATCH/Users/{id}Partially update a user (PatchOp)200
DELETE/Users/{id}Delete a user (deletes the identity)204

The {id} is the Ory identity ID (a UUID), returned as id when the user is created.

Create a user

POST /Users
Content-Type: application/scim+json
Authorization: Bearer <your-secret>
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"externalId": "ext-123",
"userName": "bjensen@example.com",
"name": { "givenName": "Barbara", "familyName": "Jensen" },
"emails": [{ "value": "bjensen@example.com", "primary": true, "type": "work" }],
"active": true
}

On success the server responds with 201 Created and the full user resource:

{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"externalId": "ext-123",
"userName": "bjensen@example.com",
"name": { "givenName": "Barbara", "familyName": "Jensen" },
"active": true,
"emails": [{ "value": "bjensen@example.com", "primary": true, "type": "work" }],
"groups": [],
"meta": {
"resourceType": "User",
"created": "2026-06-15T10:00:00Z",
"lastModified": "2026-06-15T10:00:00Z"
}
}

How the incoming attributes are applied to the Ory identity is controlled by the client's data mapping. The password attribute, if present, is stored as a password credential and is never returned in any response.

If the user already exists, the create may succeed as an update (auto-linking) or fail with a 409 conflict. See How SCIM relates to organizations and Errors.

Retrieve a user

GET /Users/9f8e7d6c-5b4a-3210-fedc-ba9876543210

Returns 200 OK and the user resource shown above.

List users

GET /Users?startIndex=1&count=20

Returns a ListResponse envelope. See Pagination for the offset and cursor variants and Filtering for the filter query parameter.

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 42,
"startIndex": 1,
"itemsPerPage": 20,
"Resources": [
{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "id": "...", "userName": "bjensen@example.com", "active": true }
]
}

Replace a user

PUT /Users/{id} replaces the user with the supplied representation. Attributes that are not present in the request are reset to their default. Use PATCH for partial updates.

Update a user (PATCH)

PATCH /Users/{id} applies a SCIM PatchOp with add, replace, and remove operations:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{ "op": "replace", "path": "active", "value": false },
{ "op": "replace", "path": "name.givenName", "value": "Babs" }
]
}
  • Schema-qualified attribute paths are accepted, for example urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department. Paths that reference an unsupported schema return 400.
  • A remove operation without a path returns 400 with scimType: noTarget.
  • Operations against read-only attributes (such as id, groups, or meta) are ignored.

Delete a user

DELETE /Users/{id} returns 204 No Content and permanently deletes the underlying Ory identity. To disable a user without deleting it, set active to false instead. See Deprovisioning identities.

User resource schema

Ory Network supports the standard SCIM user resource schema as defined in RFC 7643, Section 4.1. The following attributes are supported:

NameTypeRemarks
idUUIDRead-only, this is the identity ID.
externalIdstringOptional, an ID set by the SCIM client. Filterable (case-sensitive).
userNamestringRequired, unique identifier for the user. Typically used as the login identifier. Filterable.
nameobjectContains sub-attributes formatted, familyName, givenName, middleName, honorificPrefix, and honorificSuffix.
displayNamestring
nickNamestring
profileUrlstring
titlestring
userTypestring
preferredLanguagestring
localestring
timezonestringIf set, must be a valid time zone.
activeboolWhether the user can log in. If omitted on create or replace, defaults to true. Set to false to deactivate the user; deactivated users cannot log in.
passwordstringIf set, the user can log in with this password. The password is never returned in any SCIM response.
emailsarrayList of email addresses. Each email can have a value (string), display (string), primary (boolean), and type (string). At most one primary=true email can be set.
phoneNumbersarrayList of phone numbers. Each entry can have value, display, primary, and type. At most one primary=true entry can be set.
imsarrayList of instant messaging accounts. Each entry can have value, display, primary, and type. At most one primary=true entry can be set.
photosarrayList of photos. Each entry can have value, display, primary, and type. At most one primary=true entry can be set.
addressesarrayList of addresses. Each address can have formatted, streetAddress, locality, region, postalCode, country, and type.
groupsarrayRead-only, a list of groups the user is a direct member of. Each entry has value, display, and type. To modify, set the members property on the Groups resource.
entitlementsarrayList of entitlements. Each entry can have value, display, primary, and type. At most one primary=true entry can be set.
rolesarrayList of roles. Each entry can have value, display, primary, and type. At most one primary=true entry can be set.
x509CertificatesarrayList of X.509 certificates. Each entry can have value, display, primary, and type. At most one primary=true entry can be set.

Enterprise User extension

The server supports the SCIM Enterprise User extension (RFC 7643, Section 4.3), identified by the schema URN urn:ietf:params:scim:schemas:extension:enterprise:2.0:User. When present, the extension is returned as a top-level object keyed by the URN, and the URN is added to the resource's schemas array:

{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"],
"id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"userName": "bjensen@example.com",
"active": true,
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
"employeeNumber": "701984",
"costCenter": "4130",
"organization": "Universal Studios",
"division": "Theme Park",
"department": "Tour Operations",
"manager": { "value": "<manager-identity-id>", "displayName": "John Smith" }
}
}
NameTypeRemarks
employeeNumberstringFilterable.
costCenterstring
organizationstringA free-form string attribute; unrelated to the Ory organization the SCIM client is bound to.
divisionstring
departmentstring
managerobjectvalue is the manager's identity ID. manager.displayName is read-only and is only resolved if the manager identity is in the same organization.

Groups

MethodPathDescriptionSuccess status
GET/GroupsList or search groups200
POST/GroupsCreate a group201
GET/Groups/{id}Retrieve a group by ID200
PUT/Groups/{id}Replace a group (full update)200
PATCH/Groups/{id}Partially update a group (PatchOp)200
DELETE/Groups/{id}Delete a group204

Create a group

POST /Groups
Content-Type: application/scim+json
Authorization: Bearer <your-secret>
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"externalId": "ext-grp-1",
"displayName": "Engineering",
"members": [
{ "value": "<identity-id>", "type": "User" },
{ "value": "<group-id>", "type": "Group" }
]
}

Returns 201 Created with the group resource:

{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"id": "a1b2c3d4-...",
"externalId": "ext-grp-1",
"displayName": "Engineering",
"members": [
{ "value": "<identity-id>", "display": "bjensen@example.com", "type": "User" },
{ "value": "<group-id>", "display": "Backend", "type": "Group" }
],
"meta": {
"resourceType": "Group",
"created": "2026-06-15T10:00:00Z",
"lastModified": "2026-06-15T10:00:00Z"
}
}

Group memberships

Group memberships are managed through the members attribute on the Groups resource. Each member entry has:

  • value: an identity ID when type is "User", or a group ID when type is "Group" (nested sub-groups are supported).
  • type: "User" or "Group".
  • display: read-only, the member's userName (for users) or group name (for groups).

The groups attribute on a user resource reflects only the user's direct memberships and is read-only.

To change memberships incrementally, use PATCH /Groups/{id} with add and remove operations targeting the members path. A remove without a path returns 400 noTarget rather than removing all members.

Group resource schema

Ory Network supports the standard SCIM group resource schema as defined in RFC 7643, Section 4.2:

NameTypeRemarks
idUUIDRead-only, this is the group ID.
externalIdstringOptional, an ID set by the SCIM client. If set, it must be unique within the organization. Filterable.
displayNamestringRequired, the name of the group. Filterable.
membersarrayList of members. Each member has value, display (read-only), and type ("User" or "Group"). See above.

Pagination

The list endpoints (GET /Users and GET /Groups) support two mutually exclusive pagination methods: cursor-based and offset-based. Offset-based is used by default; cursor-based is used when a cursor query parameter is present.

tip

Prefer cursor-based pagination. It is significantly faster on large directories and has no upper bound, whereas offset-based pagination caps startIndex at 5000 and count at 1000. Use offset-based pagination only for small result sets or a quick first page.

For anything beyond a small first page, use keyset (cursor) pagination as defined in RFC 9865. It is faster on large directories and has no upper bound. Start by passing cursor with an empty value (or a known cursor), then follow nextCursor from each response until it is no longer returned:

GET /Users?count=20&cursor=
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"itemsPerPage": 20,
"nextCursor": "<opaque-cursor>",
"Resources": []
}
  • Results are ordered by id.
  • Cursors are opaque, stateless tokens that expire after one hour (cursorTimeout in ServiceProviderConfig). An expired cursor returns 400 with scimType: expiredCursor; an invalid cursor returns 400 with scimType: invalidCursor. In both cases, restart pagination from the first page.
  • nextCursor is omitted on the last page.
  • totalResults is not returned on cursor pages.

Offset-based pagination (default)

Offset-based pagination uses the standard SCIM startIndex (1-based) and count query parameters. It is the default when no cursor parameter is present, but it is capped — use cursor-based pagination for large directories.

ParameterDefaultLimit
startIndex1must be ≤ 5000
count100must be ≤ 1000

startIndex or count above the limit returns 400 with scimType: tooMany. A count of 0 returns only totalResults with no Resources array. Offset responses always include totalResults (including 0):

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 42,
"startIndex": 1,
"itemsPerPage": 20,
"Resources": []
}

Filtering

The list endpoints accept a filter query parameter. Only the eq (equals) operator is supported, and only on indexed attributes:

ResourceFilterable attributes
UsersuserName, externalId, employeeNumber, groups.value (a group UUID)
GroupsdisplayName, externalId
GET /Users?filter=userName eq "bjensen@example.com"
  • externalId filtering is case-sensitive.
  • Filtering on any other attribute returns 400 with scimType: invalidFilter ("not indexed").
  • Other operators (ne, co, sw, ew, pr, gt, and so on) are not supported.
  • A filter may reference a supported schema URN prefix; references to unsupported schemas return 400.
  • The filter query string is limited to 1024 bytes.

Filtering users by group

A user's groups.value is a group ID, so you can list the users that belong to a specific group by filtering /Users on groups.value with that group's ID:

GET /Users?filter=groups.value eq "b3f8…group-uuid"
  • The filter value must be a valid group UUID; otherwise the request returns 400 with scimType: invalidFilter and the detail The filter value for groups.value must be a valid UUID.
  • Only direct members are matched. A user who belongs to the group only through a nested sub-group is not returned — query those sub-groups separately.
  • This is the inverse of reading a group's members list (GET /Groups/{id}). It is the efficient way to enumerate a group's users, and it pairs well with cursor-based pagination for large groups.

Attribute selection

The attributes and excludedAttributes query parameters control which attributes are returned. Only one of the two may be set in a single request; setting both returns 400.

Errors

Errors are returned with an appropriate HTTP status code and a SCIM error body (RFC 7644, Section 3.12). Note that as per spec status is a string:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "409",
"scimType": "uniqueness",
"detail": "Could not create user: identity already exists in another scope"
}

scimType and detail are present only when applicable. Common error cases:

StatusscimTypeWhen it happens
400invalidSyntaxThe request body could not be decoded, or a resource failed validation (for example a missing userName, an invalid time zone, or more than one primary entry).
400invalidValueA value is malformed, for example a group member value that is not a valid UUID, or a member type other than "User" or "Group".
400invalidFilterThe filter is malformed, references a non-indexed attribute, or references an unsupported schema.
400invalidPathA PATCH path is invalid or references an unsupported attribute.
400noTargetA PATCH remove (or replace with no matching element) has no target path.
400tooManystartIndex exceeds 5000 or count exceeds 1000.
400invalidCursor / expiredCursorThe pagination cursor is invalid or has expired. Restart pagination from the first page.
401The Authorization header is missing or does not match the configured secret.
404The SCIM client, user, group, schema, or resource type does not exist — including when the resource belongs to a different organization.
409uniquenessA conflicting resource already exists. For users this includes a duplicate userName/email and the cross-organization case (see below). For groups this includes a duplicate externalId.
413The request body exceeds the 16 MiB limit.
500An internal error occurred, for example the data mapping script failed to fetch or evaluate, or a database write failed.

The most common conflict integrators encounter is provisioning a user who already exists in a different organization, which returns:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "409",
"scimType": "uniqueness",
"detail": "Could not create user: identity already exists in another scope"
}

See How SCIM relates to organizations for why this happens and how to resolve it.

Supported features

The server advertises its capabilities through GET /ServiceProviderConfig. At a glance:

FeatureSupportedNotes
PATCHYesRFC 7644 PatchOp with add, replace, remove.
FilteringYeseq operator only, on indexed attributes (see Filtering).
Change passwordYesThrough the password attribute.
Pagination (offset)YesstartIndex / count.
Pagination (cursor)Yescursor / nextCursor, RFC 9865.
Enterprise User extensionYesRFC 7643 §4.3.
SortingNosortBy / sortOrder are not supported.
ETag / versioningNo
Bulk operationsNoNo /Bulk endpoint.
/Me endpointNo