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 /v1/orgs/{org_id}/scim/token/rotate
Authorization: Bearer arb_live_your-api-key-here

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.


ResourceEndpointsDescription
Users/scim/v2/UsersIndividual user accounts
Groups/scim/v2/GroupsUser groups with optional Arbitex extension attributes
Schemas/scim/v2/SchemasSchema discovery (read-only)

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

Query parameters:

ParameterDefaultDescription
startIndex11-based pagination start index
count100Maximum results per page (max 1000)
filterSCIM 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": "alice@example.com",
"displayName": "Alice Smith",
"emails": [
{ "value": "alice@example.com", "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": "alice@example.com",
"displayName": "Alice Smith-Jones",
"emails": [
{ "value": "alice@example.com", "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 attributeArbitex fieldNotes
userNameemail / usernameUsed as both email and username in Arbitex
emails[primary=true].valueemailPreferred email source when present
displayNameusernameDisplay name
externalId(stored for IdP linkage)Used to correlate with IdP directory objects
activeis_activeSCIM active=false deactivates the account
SCIM attributeArbitex fieldNotes
displayNamenameGroup display name
externalIdexternal_group_idIdP group ID for SSO claim mapping
members[].valuegroup_membershipsUser 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:

AttributeTypeDescription
dlpPolicystringDLP policy action override: SKIP, BLOCK, CANCEL, or REDACT
modelAccessarrayList of permitted model identifiers
complianceBundlesarrayCompliance bundle IDs to activate for this group
quotaTokensintegerPer-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:

FilterExample
userName eqfilter=userName eq "alice@example.com"
email eqfilter=email eq "alice@example.com"
externalId eqfilter=externalId eq "00u1abcdef1234567890"

Groups:

FilterExample
displayName eqfilter=displayName eq "Engineering"
externalId eqfilter=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 /v1/orgs/{org_id}/scim/token/rotate with your admin API 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 /v1/orgs/{org_id}/scim/token/rotate 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 /v1/orgs/{org_id}/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