SCIM provisioning in your tenant
SCIM lets a system of record, such as an HR system, create, update and remove your tenant's users and groups as people join, move and leave.
This page is a console for your tenant's SCIM 2.0 API. Connect a provisioning client, get an access token, then work through every method in order: discovery, users, groups, bulk requests and clean-up. Each step shows the exact request and the response your tenant returned, and fills in the ids and versions the next step needs.
Connect to your tenant
Requests on this page are real. They go from your browser straight to your tenant, change its users and groups, and appear in its Audit and Logs. The client secret and access token stay in this page's memory and are gone when you leave it.
Create a provisioning client for me
Creates a confidential client in the tenant you chose. It may use only the client credentials grant, holds the SCIM scopes you pick, and gets a new secret, which is filled in above. You can manage or delete it on the tenant's Clients page.
Sign in with a BTL account that can create OAuth clients and their secrets in a tenant to do this in one step. Otherwise create the client by hand: allow the client credentials grant in Flow policy, create a confidential client with that grant, assign it a SCIM scope, and generate its secret.
POST/oauth/token
1. Get an access tokenNot sent
The client signs in with its ID and secret using the client credentials grant and asks for one SCIM scope. The access token it receives goes in the Authorization: Bearer header of every SCIM request until it expires.
POST /oauth/token
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&scope=scim-<id>
Discover what the API supports
A SCIM client usually starts by reading what the service supports and the attributes it stores. Any SCIM scope can read these documents.
GET/ServiceProviderConfig
2. Read the service configurationNot sent
Which optional SCIM features this service supports: PATCH, Bulk with its limits, filtering with its maximum results, sorting, ETags and password changes, and how to authenticate.
Scopes: any SCIM scope (scim-<id>, scim-<id>.read, scim-<id>.users, scim-<id>.groups, scim-<id>.passwords)
GET/ResourceTypes
3. List resource typesNot sent
The kinds of resources this service manages, User and Group, with each one's endpoint and schemas.
Scopes: any SCIM scope (scim-<id>, scim-<id>.read, scim-<id>.users, scim-<id>.groups, scim-<id>.passwords)
GET/ResourceTypes/{id}
4. Read one resource typeNot sent
One resource type. The User type lists the enterprise extension, which carries employee number, department and manager.
Scopes: any SCIM scope (scim-<id>, scim-<id>.read, scim-<id>.users, scim-<id>.groups, scim-<id>.passwords)
GET/Schemas
5. List schemasNot sent
Every attribute this tenant stores, with its type, whether it is required, and whether it can be changed. Attributes the tenant does not store are left out, so a client can see exactly what persists.
Scopes: any SCIM scope (scim-<id>, scim-<id>.read, scim-<id>.users, scim-<id>.groups, scim-<id>.passwords)
GET/Schemas/{id}
6. Read one schemaNot sent
One schema by its URN.
Scopes: any SCIM scope (scim-<id>, scim-<id>.read, scim-<id>.users, scim-<id>.groups, scim-<id>.passwords)
Users
Create a user, read it back, find it, then change it. Each step fills in the id and version from the one before it.
POST/Users
7. Create a userNot sent
A user needs a userName, a given and family name, and a work email. userName, externalId and email must be unique in the tenant. The response is 201 with the new user, its id, and its version in the ETag header. Add a password only when the tenant accepts passwords over SCIM and the client holds the passwords scope.
Scopes: scim-<id>, scim-<id>.users
GET/Users/{id}
8. Read a userNot sent
One user by id. The password is never returned.
Scopes: scim-<id>, scim-<id>.read, scim-<id>.users, scim-<id>.groups
GET/Users
9. List and filter usersNot sent
Users that match a filter, a page at a time. totalResults counts every match; Resources holds this page.
Scopes: scim-<id>, scim-<id>.read, scim-<id>.users, scim-<id>.groups
POST/Users/.search
10. Search users with a request bodyNot sent
The same search as listing, with the parameters in the body. Use it when a filter is too long or too sensitive for a URL.
Scopes: scim-<id>, scim-<id>.read, scim-<id>.users, scim-<id>.groups
PATCH/Users/{id}
11. Update part of a userNot sent
Changes only the attributes named in the operations. Setting active to false locks the user and ends their sessions and tokens. The response has the updated user and its new ETag.
Scopes: scim-<id>, scim-<id>.users
PUT/Users/{id}
12. Replace a userNot sent
Replaces every attribute with the body. Attributes left out are cleared. This example also sets active back to true, which unlocks the user.
Scopes: scim-<id>, scim-<id>.users
Groups
Groups hold tenant users, for example by department. They carry no permissions. These steps use the user you created above as a member.
POST/Groups
13. Create a groupNot sent
A group needs a displayName that is unique in the tenant. Members are user ids; groups cannot contain groups.
Scopes: scim-<id>, scim-<id>.groups
GET/Groups/{id}
14. Read a groupNot sent
One group with its members.
Scopes: scim-<id>, scim-<id>.read, scim-<id>.groups
GET/Groups
15. List and filter groupsNot sent
Groups that match a filter. Add members to excludedAttributes to keep large groups out of the response.
Scopes: scim-<id>, scim-<id>.read, scim-<id>.groups
POST/Groups/.search
16. Search groups with a request bodyNot sent
The same search as listing, with the parameters in the body.
Scopes: scim-<id>, scim-<id>.read, scim-<id>.groups
PATCH/Groups/{id}
17. Change a group's membersNot sent
Adds and removes members without sending the whole list, which keeps large groups cheap to change. A remove whose filter matches no member is refused with noTarget.
Scopes: scim-<id>, scim-<id>.groups
PUT/Groups/{id}
18. Replace a groupNot sent
Replaces the name, externalId and the whole member list with the body.
Scopes: scim-<id>, scim-<id>.groups
Bulk requests
Bulk sends several operations in one request. Later operations can refer to resources created earlier in the same request by their bulkId.
POST/Bulk
19. Send several operations at onceNot sent
Up to 100 operations run in order, each with its own result and audit record. This example creates a user and a group, changes the user, then deletes both, so it leaves nothing behind. failOnErrors stops after that many errors.
Scopes: scim-<id>
Clean up
Delete the group and the user you created, so your tenant is as it was.
DELETE/Groups/{id}
20. Delete a groupNot sent
Deletes the group. Its members stay in the tenant. The response is 204 with no body.
Scopes: scim-<id>, scim-<id>.groups
DELETE/Users/{id}
21. Delete a userNot sent
Deletes the user, ends their access, and frees their userName and externalId for a rehire. To keep a user but stop their access, set active to false instead.
Scopes: scim-<id>, scim-<id>.users
Built-in scopes
Every tenant has five SCIM scopes named after the first six characters of its tenant ID. They cannot be deleted, and they are always exclusive: a client can request one only after you assign it. Removing an assignment or disabling the client stops its SCIM access at once, even for tokens it already holds.
| Scope | Allows |
|---|---|
scim-3f9a1c | Everything below. |
scim-3f9a1c.read | Discovery and reading users and groups. |
scim-3f9a1c.users | Creating, updating, locking, unlocking and deleting users. |
scim-3f9a1c.groups | Creating, updating and deleting groups and their members. |
scim-3f9a1c.passwords | Setting user passwords, together with the users scope. |
No SCIM scope assigns management roles, changes tenant settings or reads Audit and Logs.
Users and passwords
The enterprise extension stores the employee number, cost center, organization, division, department and manager. Attributes the tenant does not store are ignored. A user who holds tenant management roles cannot be changed over SCIM; an administrator manages them in the portal.
Setting active to false locks the user and ends their sessions and tokens; true unlocks them. DELETE removes the user and frees the userName and externalId for a rehire. A password must meet the tenant's password rules; it is stored as a hash and never returned.
Custom schemas
The Schemas page under User Management adds your own extension schemas. Each has a URN you choose, such as urn:example:hr:2.0:User, and attributes of type string, boolean, integer, decimal or dateTime. An attribute can take several values (up to 20), and you choose whether it is required, case-sensitive, unique in the tenant, set once, and returned in every response or only when a client asks for it with attributes. Text attributes can also have a maximum length and a list of allowed values.
Clients send the values under the schema URN, exactly like the enterprise extension: "urn:example:hr:2.0:User": {"badge": "B-100", "skills": ["Go", "SQL"]}. /Schemas and /ResourceTypes/User list your schemas, and filters, sorting and PATCH paths accept the full name, such as urn:example:hr:2.0:User:skills[value eq "Go"]. A short name such as badge also works when no standard attribute or other custom attribute uses it. Values that break a rule are refused with 400 and the matching scimType; a value another user already holds in a unique attribute is refused with 409 uniqueness.
An attribute's name, type and whether it takes several values are fixed after creation. Deleting an attribute or a schema removes its stored values from every user and gives those users a new version. Each tenant has its own schemas, up to 10 with 100 attributes in total, shown under Usage and limits. Nested (complex) attributes and extensions for groups are not available.
Settings and limits
The Provisioning page controls whether the API is on, whether it accepts passwords, whether a new user whose email matches a user created by an administrator is refused or linked, which roles provisioned users receive, and lower request and password budgets for the tenant. SCIM requests and password changes each have a tenant-wide budget per minute. A request over budget receives 429 with Retry-After. Browsers also send a preflight check before calling the API from another site, such as this page; those checks have their own small budget and never spend the SCIM budget. All of these budgets appear under Usage and limits on the Overview page.
Only this website can read SCIM and token responses in a browser. Provisioning integrations normally run on a server, where no browser rule applies.
Audit and Logs
SCIM activity appears in the User directory source of Audit and Logs, and clients created on this page appear in the OAuth management source. Each change names the attributes it changed, never their values. Repeated reads and refusals from one client are summarized once a minute with a request count. Search by request ID or correlation ID to find a single request.
The HR Simulator
The HR Simulator, linked from the Provisioning page, acts as an HR system. It uses a client you configure to onboard, update and offboard fictional people through your tenant's SCIM API on a schedule, and shows each request's correlation ID so you can find it in Audit.