Skip to content

SCIM 2.0 Provisioning

Arbitex implements the System for Cross-domain Identity Management (SCIM) 2.0 protocol (RFC 7644) for automated user and group lifecycle management from your identity provider. SCIM provisioning keeps your Arbitex users and groups in sync with your IdP directory without manual imports.

For Entra ID-specific setup (Entra ID Enterprise App gallery configuration), see the Entra ID SCIM guide. This guide covers IdP-agnostic setup that applies to Okta, OneLogin, JumpCloud, and any SCIM 2.0-compliant IdP.


SCIM provisioning automates:

  • User lifecycle — create users when they are assigned to the Arbitex app in your IdP, deactivate users when they are removed or deprovisioned
  • Group sync — create and maintain Arbitex groups that mirror IdP groups; sync group membership changes
  • Attribute updates — propagate display name, email, and external ID changes from the IdP to Arbitex

Without SCIM, users must be manually invited via the Arbitex admin panel, and group membership must be managed separately in both systems.


All SCIM endpoints are under:

https://api.arbitex.ai/scim/v2

Schema discovery:

https://api.arbitex.ai/scim/v2/Schemas

SCIM endpoints require a Bearer token in the Authorization header:

Authorization: Bearer <scim-token>

A missing or invalid token returns 401:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "401",
"detail": "SCIM authentication required"
}

If SCIM provisioning is not configured (no token set), requests return 403:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "403",
"detail": "SCIM provisioning is not configured (no bearer token set)"
}

Arbitex supports per-org SCIM tokens, stored as bcrypt hashes. To rotate your org’s SCIM token:

POST /api/v1/scim/token/rotate
Authorization: Bearer arb_live_your-api-key-here

The endpoint always acts on the authenticated admin’s own org — the target org is derived from the credential in the Authorization header. You do not supply an org identifier as a path segment, a body field, or a header, so an admin cannot rotate another organisation’s token.

Response:

{
"token": "raw-token-value",
"org_id": "8d4b2c1e-0a3f-4e9d-b7c6-1a2b3c4d5e6f",
"created_at": "2026-03-11T00:00:00+00:00"
}

When you rotate, the previous active token is immediately invalidated. Update your IdP SCIM configuration with the new token before or immediately after rotation to avoid a provisioning sync failure.


Resource Endpoints Description
Users /scim/v2/Users Individual user accounts
Groups /scim/v2/Groups User groups with optional Arbitex extension attributes
Schemas /scim/v2/Schemas Schema discovery (read-only)

GET /scim/v2/Users
Authorization: Bearer <scim-token>

Query parameters:

Parameter Default Description
startIndex 1 1-based pagination start index
count 100 Maximum results per page (max 1000)
filter SCIM filter expression (see Filtering)

Response:

{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 47,
"startIndex": 1,
"itemsPerPage": 100,
"Resources": [...]
}
GET /scim/v2/Users/{user_id}
Authorization: Bearer <scim-token>

Returns a single SCIM User resource. Returns 404 if not found.

POST /scim/v2/Users
Authorization: Bearer <scim-token>
Content-Type: application/json
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "[email protected]",
"displayName": "Alice Smith",
"emails": [
{ "value": "[email protected]", "primary": true }
],
"active": true,
"externalId": "00u1abcdef1234567890"
}

Returns 201 with the created SCIM User resource. Returns 409 if userName already exists.

SCIM-provisioned users are created with a randomly generated password — they authenticate via SSO, not local password. SCIM provisioning is designed to work alongside SSO (SAML or OIDC).

PUT /scim/v2/Users/{user_id}
Authorization: Bearer <scim-token>
Content-Type: application/json
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "[email protected]",
"displayName": "Alice Smith-Jones",
"emails": [
{ "value": "[email protected]", "primary": true }
],
"active": true,
"externalId": "00u1abcdef1234567890"
}

Returns 200 with the updated resource. Returns 404 if not found, 409 on uniqueness conflict.

PATCH /scim/v2/Users/{user_id}
Authorization: Bearer <scim-token>
Content-Type: application/json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{ "op": "replace", "path": "active", "value": false }
]
}

Applies partial updates. Used by IdPs to deactivate a user when they are deprovisioned.

DELETE /scim/v2/Users/{user_id}
Authorization: Bearer <scim-token>

SCIM DELETE is a soft-delete. Arbitex sets is_active=false on the user record rather than physically deleting it. This preserves audit trail and conversation history. Returns 204 No Content.


GET /scim/v2/Groups
Authorization: Bearer <scim-token>

Same pagination and filter parameters as Users.

GET /scim/v2/Groups/{group_id}
Authorization: Bearer <scim-token>

Returns the SCIM Group resource, including Arbitex extension attributes if present.

POST /scim/v2/Groups
Authorization: Bearer <scim-token>
Content-Type: application/json
{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:Group",
"urn:arbitex:scim:schemas:extension:Group:2.0"
],
"displayName": "Engineering",
"externalId": "grp_0001",
"members": [
{ "value": "user-uuid-1" },
{ "value": "user-uuid-2" }
]
}

Returns 201 with the created SCIM Group resource. Returns 409 if displayName already exists.

Full group replacement, including updating the members list and any Arbitex extension attributes.

Used by IdPs to add or remove individual members from a group. Operations include add and remove for the members path.

DELETE /scim/v2/Groups/{group_id}
Authorization: Bearer <scim-token>

Deletes the group and all its memberships. Returns 204 No Content.


SCIM attribute Arbitex field Notes
userName email / username Used as both email and username in Arbitex
emails[primary=true].value email Preferred email source when present
displayName username Display name
externalId (stored for IdP linkage) Used to correlate with IdP directory objects
active is_active SCIM active=false deactivates the account
SCIM attribute Arbitex field Notes
displayName name Group display name
externalId external_group_id IdP group ID for SSO claim mapping
members[].value group_memberships User UUIDs in membership junction table

Arbitex supports a custom SCIM schema extension for provisioning group-level policy configuration:

Schema URN: urn:arbitex:scim:schemas:extension:Group:2.0

Extension attributes:

Attribute Type Description
dlpPolicy string DLP policy action override: SKIP, BLOCK, CANCEL, or REDACT
modelAccess array List of permitted model identifiers
complianceBundles array Compliance bundle IDs to activate for this group
quotaTokens integer Per-group daily token budget

These extension attributes allow IdP administrators to configure Arbitex group policies directly from their IdP provisioning interface, without requiring separate configuration in the Arbitex admin panel.


SCIM filter expressions use the format attribute op value. Arbitex supports basic equality filters on key attributes:

Users:

Filter Example
userName eq filter=userName eq "[email protected]"
email eq filter=email eq "[email protected]"
externalId eq filter=externalId eq "00u1abcdef1234567890"

Groups:

Filter Example
displayName eq filter=displayName eq "Engineering"
externalId eq filter=externalId eq "grp_0001"

Unsupported filter expressions return the full unfiltered list (not a 400 error) — the IdP is responsible for any client-side filtering of the result set.


The following steps apply to any SCIM 2.0-compliant identity provider:

  1. Generate a SCIM token — Use POST /api/v1/scim/token/rotate with your admin API key. The token is issued for the org that owns that key. Copy the returned raw token immediately.

  2. Configure your IdP — In your IdP’s SCIM provisioning settings, enter:

    • SCIM base URL: https://api.arbitex.ai/scim/v2
    • Authentication method: Bearer token
    • Bearer token: The raw token from step 1
  3. Map attributes — Configure user attribute mappings per the Attribute mapping table. At minimum, map userName to the user’s primary email.

  4. Test the connection — Most IdPs provide a “Test connection” button that performs a GET /scim/v2/Users?count=1 request. Verify it returns success.

  5. Enable provisioning — Enable “Create”, “Update”, and “Deactivate” provisioning operations. Most IdPs also support group sync — enable it to synchronize groups and memberships.

  6. Initial sync — Trigger a manual full sync to import existing users and groups. Monitor the IdP’s provisioning logs for any errors.

In Okta, add a custom SCIM 2.0 app (no gallery app is required — Arbitex uses the standard SCIM 2.0 protocol). Set the SCIM connector base URL, select Bearer Token authentication, and configure the attribute mappings. Enable both user and group provisioning features.

In OneLogin, create a SCIM Provisioner with SAML 2.0 or a custom connector. Enter the base URL and bearer token. Map the SCIM userName field to the user’s email address.

In JumpCloud, use the Custom SCIM 2.0 integration type. Enter the base URL and bearer token under the “API type” → “SCIM 2.0” option. Enable group push to synchronize JumpCloud user groups as Arbitex groups.

Any IdP that implements RFC 7644 SCIM 2.0 can provision to Arbitex. Configure the base URL as https://api.arbitex.ai/scim/v2 and authenticate with the Bearer token. The standard SCIM User and Group schemas are supported without additional configuration.


  1. Token rejected (401) — The SCIM token may have been rotated. Verify the token in your IdP matches the most recently issued token. Rotate and update if uncertain.
  2. Duplicate userName (409) — A user with the same userName (email) already exists in Arbitex. If the user was created manually before SCIM was configured, update their externalId to match the IdP’s ID, or delete the duplicate and allow SCIM to re-create.
  3. SCIM not configured (403) — No SCIM token is set for the org. Run POST /api/v1/scim/token/rotate, authenticated as an admin of that org, to create one.

When a SCIM user update fails due to a uniqueness conflict (409), it means the new userName or email is already taken by another user in the system. This typically occurs when:

  • The same email exists under a different externalId
  • A user was imported with a typo that was corrected in the IdP

Resolution: identify the conflicting user in Arbitex admin, update or remove the conflict, then trigger a re-sync from the IdP.

SCIM tokens do not expire automatically — they remain active until rotated. If provisioning stops working, the likely cause is a token rotation (deliberate or accidental) that was not reflected in the IdP configuration. Re-run POST /api/v1/scim/token/rotate and update the IdP immediately.

Some IdPs sync users and groups independently. Ensure:

  • Group provisioning is enabled in the IdP (not just user provisioning)
  • The group is assigned to the Arbitex app in the IdP
  • Member UUIDs in SCIM PATCH operations use the Arbitex user UUIDs returned from GET /scim/v2/Users, not the IdP’s internal user IDs

Deactivated users still appearing as active

Section titled “Deactivated users still appearing as active”

SCIM DELETE sets is_active=false (soft-delete). If a user shows as active after deletion in the IdP:

  1. Verify the IdP sent a DELETE (or PATCH with active=false) — check the IdP’s provisioning log
  2. Verify the user’s is_active field in Arbitex via GET /scim/v2/Users/{id}
  3. If the DELETE arrived, the user should be inactive. If not, confirm the SCIM endpoint URL includes the correct user UUID