SCIM User Provisioning
Viven supports automated user provisioning through the SCIM 2.0 protocol. Once configured, your identity provider (IdP) — such as Okta, Microsoft Entra ID, or any SCIM-compliant system — can automatically create, update, enable, and disable Viven users and manage their roles, without manual work in the Admin Console.
This page is a reference for the Viven SCIM Users endpoint: how to authenticate, what each operation does, and how roles are interpreted.
For generating a SCIM bearer token and configuring your IdP in the Admin Console, see Employees.
Before you begin
To connect your IdP you need three things:
- Your SCIM base URL —
https://<your-viven-host>/scim/v2 - Your tenant domain (group ID) — passed as a
?domain=<group_id>query parameter on every request - A SCIM bearer token — generated in Admin Console → Employees → SCIM Token
In your IdP's provisioning configuration, set the base URL and supply the token as an HTTP bearer credential. The domain parameter must be appended to the endpoint URLs your IdP calls.
Note on user identity: In Viven's SCIM implementation, a user's email address is their unique ID. The
userNamefield and the user ID in the URL path are both the user's email. There is no separate opaque identifier.
Authentication
Every request must include the bearer token issued for your tenant:
Authorization: Bearer <your-scim-token>
Requests are also scoped to a tenant. Always include the domain query parameter identifying your organization's group:
?domain=<group_id>
If the token is missing or incorrect, the request is rejected with 403 Not Authorized. If the domain is missing or not configured for SCIM, the request is rejected with 400.
Endpoints
Base path: /scim/v2/Users
| Operation | Method & path |
|---|---|
| Check if a user exists | GET /scim/v2/Users?filter=userName eq "<email>" |
| Get a single user | GET /scim/v2/Users/<email> |
| Create or replace a user | POST /scim/v2/Users or PUT /scim/v2/Users/<email> |
| Update specific fields | PATCH /scim/v2/Users/<email> |
| Delete a user | DELETE /scim/v2/Users/<email> (not supported — see below) |
Looking up users (GET)
Check whether a user exists
This is the lookup most IdPs use during provisioning:
GET /scim/v2/Users?filter=userName eq "user@company.com"
| Result | Response |
|---|---|
| User exists in your tenant | totalResults: 1, with the user in Resources |
| User not found in your tenant | totalResults: 0, empty Resources |
Only the userName eq "..." filter is supported.
Get a single user
GET /scim/v2/Users/user@company.com
Returns the user record (200) or 404 User does not exist.
Listing all users
Listing every user (GET /scim/v2/Users with no filter) is not supported and returns 400. Look users up individually by email or with the userName filter.
Creating and replacing users (POST / PUT)
Send POST /scim/v2/Users or PUT /scim/v2/Users/<email> to create a user — or fully replace one if they already exist.
Supported fields
| Field | Meaning |
|---|---|
userName | The user's email (also used as the ID) |
name.givenName | First name |
name.familyName | Last name |
title | Job title |
externalId | Your IdP's identifier for the user |
active | Account status — true enables the account, false disables it |
roles | The user's Viven roles (see Roles) |
Updating users (PATCH)
Use PATCH /scim/v2/Users/<email> to change specific fields without replacing the whole record. The user must already exist, otherwise the request returns 404 User does not exist.
PATCH reads each entry in the Operations array (and a top-level active field, if present). You can update:
active— enable or disable the accounttitle— job titleexternalId— your IdP's identifierroles— replaces the user's Viven roles
A PATCH only touches the fields you include. For example, patching only title leaves the user's roles untouched. Roles are only changed when roles is part of the request.
Roles
Roles control what a user can do in Viven. The following role IDs are valid:
| Role ID | Description |
|---|---|
digital_twin_org_admin | Organization administrator |
digital_twin_setup_admin | Setup administrator |
digital_twin_self_serve_setup_admin | Self-serve setup administrator |
digital_twin_data_analyst | Data analyst |
digital_twin_agent_builder | Agent builder |
digital_twin_user | Standard full user |
digital_twin_light_user | Light (limited) user |
For what each role can access in the product, see Digital Twin Roles.
How roles are interpreted
When you send a roles array, Viven normalizes it with a few rules. Understanding these prevents surprises:
- An unrecognized role name rejects the whole request with 400 Invalid role(s).
- Light user must stand alone.
digital_twin_light_useris only honored when it is the only role sent. If you combine it with any other role, the light-user role is dropped. - The standard full-user role is implicit.
digital_twin_useris not stored explicitly. If you send it alongside other roles, it is dropped from what's stored; if a user ends up with no explicit roles, Viven treats them as a standard full user automatically.
A consequence worth noting: a user with no explicit roles is a full user, not a user with no access. This is why the SCIM response can show an empty roles array for a fully-provisioned standard user.
Examples of how role requests resolve
| You send | The user effectively becomes |
|---|---|
roles omitted (on create) | Your tenant's default role, or a standard full user |
["digital_twin_light_user"] | Light user |
["digital_twin_setup_admin"] | Setup admin |
["digital_twin_data_analyst", "digital_twin_setup_admin"] | Data analyst + setup admin |
["digital_twin_light_user", "digital_twin_setup_admin"] | Setup admin (light dropped) |
["digital_twin_user", "digital_twin_setup_admin"] | Setup admin |
["digital_twin_light_user", "digital_twin_user"] | Standard full user |
["invalid_role"] | Rejected — 400 |
Light users skip the in-app onboarding flow automatically when provisioned via SCIM.
Deleting users
DELETE is not supported. The request returns 200 with an informational message and does not remove the user:
Deletion of Users is not supported at the moment, please contact your administrator to delete the user.
To deprovision a user, disable them instead by setting active to false via PUT or PATCH. To fully delete an account, contact your Viven administrator.
User response format
Successful user operations return a SCIM user object:
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "user@company.com",
"userName": "user@company.com",
"name": { "givenName": "Jane", "familyName": "Doe" },
"displayName": "Jane Doe",
"roles": ["digital_twin_setup_admin"],
"active": true,
"title": "Engineering Manager",
"externalId": "0oa1b2c3d4",
"timezone": "",
"locale": "",
"meta": { "resourceType": "User" }
}
The roles array lists only explicitly assigned roles. A standard full user may show an empty roles array (see Roles).
Error reference
| Scenario | HTTP status |
|---|---|
Missing or invalid domain / SCIM not configured for tenant | 400 |
| Missing or incorrect bearer token | 403 |
Missing user email / userName | 400 |
| User not found (GET single / PATCH) | 404 |
| Listing all users (no filter) | 400 |
| Invalid role name | 400 |
| DELETE user | 200 (informational; no deletion occurs) |
| Unsupported HTTP method | 400 |
Examples
Create or replace a user with roles
curl -X PUT "https://<your-viven-host>/scim/v2/Users/user@company.com?domain=company.com" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "user@company.com",
"name": { "givenName": "Jane", "familyName": "Doe" },
"active": true,
"roles": ["digital_twin_data_analyst", "digital_twin_setup_admin"]
}'
Change a user to a light user
curl -X PATCH "https://<your-viven-host>/scim/v2/Users/user@company.com?domain=company.com" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [{
"op": "replace",
"value": { "roles": ["digital_twin_light_user"] }
}]
}'
Disable (deprovision) a user
curl -X PATCH "https://<your-viven-host>/scim/v2/Users/user@company.com?domain=company.com" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [{
"op": "replace",
"value": { "active": false }
}]
}'
Check whether a user exists
curl "https://<your-viven-host>/scim/v2/Users?domain=company.com&filter=userName%20eq%20%22user@company.com%22" \
-H "Authorization: Bearer <token>"