SCIM 2.0 Provisioning
SCIM 2.0 (System for Cross-domain Identity Management, RFC 7643/7644) is an open API standard that lets your identity provider automatically create, update, and deprovision users in Ithbat IAM. Instead of managing user accounts in two places, changes in your IdP (Okta, Azure AD, etc.) propagate to Ithbat automatically — typically within seconds.
Without SCIM, a user's account in Ithbat persists even after they leave your organization. With SCIM, deprovisioning happens automatically when the IdP marks the user inactive or deletes them.
SCIM base URL
https://api.ithbat.io/scim/v2
All SCIM endpoints are relative to this base. Discovery endpoints are available without authentication:
| Endpoint | Description |
|---|---|
GET /scim/v2/ServiceProviderConfig | SCIM capabilities of Ithbat |
GET /scim/v2/ResourceTypes | Supported resource types (User, Group) |
GET /scim/v2/Schemas | Full attribute schemas |
Enabling SCIM for your tenant
Step 1 — Enable SCIM
SCIM is available on Growth and Enterprise plans. In the admin console, go to Settings → Provisioning → SCIM and toggle SCIM to Enabled.
Step 2 — Generate a bearer token
- Go to Settings → Provisioning → SCIM → Tokens.
- Click Generate Token.
- Copy the token immediately — it is shown only once.
You can create multiple tokens (e.g., one per integration) and revoke them individually.
POST /api/v1/scim/tokens
Authorization: Bearer {admin_token}
X-Tenant-ID: {tenant_id}
Response:
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"token": "scim_live_abc123...",
"createdAt": "2026-02-24T10:00:00Z"
}
Step 3 — Configure your IdP
Provide your IdP with:
- SCIM base URL:
https://api.ithbat.io/scim/v2 - Bearer token: the token generated above
Authentication
Every SCIM request must include the bearer token in the Authorization header:
Authorization: Bearer scim_live_abc123...
SCIM tokens are separate from user access tokens and do not expire by default. Revoke them from the admin console or via the API if they are compromised.
Supported resources
Users
Full lifecycle support: create, read, update, patch, delete, list with filter.
Endpoint: /scim/v2/Users
SCIM → Ithbat attribute mapping
| SCIM attribute | Ithbat field | Notes |
|---|---|---|
userName | email | Must be a valid email address |
name.givenName | firstName | |
name.familyName | lastName | |
name.formatted | display name fallback | Used if given/family names are absent |
emails[primary=true].value | email | Preferred over userName |
active | status | false → suspended, true → active |
phoneNumbers[primary=true].value | phone | |
locale | locale | BCP 47 language tag |
externalId | externalId | Your IdP's user ID for correlation |
Example: Create user request
POST /scim/v2/Users
Authorization: Bearer scim_live_abc123...
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "[email protected]",
"name": {
"givenName": "Jane",
"familyName": "Doe"
},
"emails": [
{
"value": "[email protected]",
"primary": true
}
],
"active": true,
"externalId": "00u1abc2defGHIJK"
}
Example: Create user response
HTTP/1.1 201 Created
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"externalId": "00u1abc2defGHIJK",
"userName": "[email protected]",
"name": {
"givenName": "Jane",
"familyName": "Doe",
"formatted": "Jane Doe"
},
"emails": [
{
"value": "[email protected]",
"primary": true
}
],
"active": true,
"meta": {
"resourceType": "User",
"created": "2026-02-24T10:00:00Z",
"lastModified": "2026-02-24T10:00:00Z",
"location": "https://api.ithbat.io/scim/v2/Users/3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
}
Example: Patch user (deactivate)
PATCH /scim/v2/Users/{id}
Authorization: Bearer scim_live_abc123...
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{
"op": "replace",
"path": "active",
"value": false
}
]
}
Setting active to false suspends the user's account. All active sessions are invalidated.
Groups
Full lifecycle support: create, read, update, patch, delete, list with filter.
Endpoint: /scim/v2/Groups
SCIM → Ithbat group mapping
| SCIM attribute | Ithbat field |
|---|---|
displayName | name |
externalId | externalId |
members[].value | Group member user IDs |
Example: Create group
POST /scim/v2/Groups
Authorization: Bearer scim_live_abc123...
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"displayName": "Engineering",
"externalId": "00g1abc2defGHIJK",
"members": [
{
"value": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"display": "[email protected]"
}
]
}
Example: Patch group members
PATCH /scim/v2/Groups/{id}
Authorization: Bearer scim_live_abc123...
Content-Type: application/scim+json
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{
"op": "add",
"path": "members",
"value": [
{
"value": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}
]
}
]
}
Listing and filtering
Ithbat supports the SCIM filter syntax on the filter query parameter.
List users
GET /scim/v2/Users?startIndex=1&count=100
Filter by userName
GET /scim/v2/Users?filter=userName eq "[email protected]"
Filter by externalId
GET /scim/v2/Users?filter=externalId eq "00u1abc2defGHIJK"
Paginate
GET /scim/v2/Users?startIndex=101&count=100
Response includes totalResults, startIndex, and itemsPerPage per the SCIM spec.
Provider-specific setup guides
Okta SCIM
Prerequisites
Your Okta application must support SCIM provisioning. Use either a SCIM 2.0 template app or a custom app with SCIM enabled.
Step 1 — Add provisioning to your Okta app
In Okta admin, open your application and go to the Provisioning tab. Click Configure API Integration and enable it.
Step 2 — Configure the SCIM connection
| Field | Value |
|---|---|
| SCIM connector base URL | https://api.ithbat.io/scim/v2 |
| Unique identifier field | userName |
| Authentication mode | HTTP Header |
| Authorization | Bearer scim_live_abc123... |
Click Test API Credentials to verify, then Save.
Step 3 — Enable provisioning actions
Under To App, enable:
- Create Users
- Update User Attributes
- Deactivate Users
Under To Okta, enable:
- Sync Password (optional)
Step 4 — Attribute mapping
Go to Provisioning → Attribute Mappings and verify that userName maps to the Okta login (email) field.
Step 5 — Assign users
Go to Assignments and assign users or groups. Each assignment triggers a SCIM create/update call.
Azure AD (Entra ID) SCIM
Step 1 — Open your Enterprise Application
In Azure portal, go to Entra ID → Enterprise applications, open your app, and select Provisioning.
Step 2 — Configure the connection
| Field | Value |
|---|---|
| Provisioning Mode | Automatic |
| Tenant URL | https://api.ithbat.io/scim/v2 |
| Secret Token | scim_live_abc123... |
Click Test Connection to verify, then Save.
Step 3 — Attribute mappings
Go to Mappings and open Provision Azure Active Directory Users. Verify these mappings exist (add if missing):
| Azure AD attribute | SCIM attribute |
|---|---|
userPrincipalName | userName |
givenName | name.givenName |
surname | name.familyName |
mail | emails[type eq "work"].value |
accountEnabled | active |
objectId | externalId |
Step 4 — Scope users
Under Settings → Scope, choose Sync only assigned users and groups and then assign the relevant users and groups under the app's Users and groups tab.
Step 5 — Start provisioning
Click Start provisioning. Azure will perform an initial sync within ~40 minutes. You can monitor progress from the Provisioning logs tab.
Error handling and sync troubleshooting
View SCIM logs
GET /api/v1/scim/logs
Authorization: Bearer {admin_token}
X-Tenant-ID: {tenant_id}
Each log entry records the incoming request method, resource type, status code, and error message if applicable.
Common errors
| Status | Meaning | Resolution |
|---|---|---|
401 Unauthorized | Invalid or revoked SCIM token | Generate a new token and update your IdP |
404 Not Found (on update) | User not found by ID | The IdP has a stale ID; trigger a re-sync |
409 Conflict | Email already exists | A user with that email was created outside SCIM; the IdP should send a PATCH instead of POST |
400 Bad Request | Missing required field | Check that userName is set and contains a valid email |
422 Unprocessable Entity | Plan user limit reached | Upgrade your plan or remove inactive users |
Force a re-sync
If Okta or Azure AD is out of sync, trigger a full re-sync from the IdP:
- Okta: Go to Provisioning → Import, click Import Now → Full Import.
- Azure AD: In provisioning settings, click Restart provisioning.
SCIM config API
Get SCIM configuration
GET /api/v1/scim/config
Authorization: Bearer {admin_token}
X-Tenant-ID: {tenant_id}
Update SCIM configuration
PUT /api/v1/scim/config
Authorization: Bearer {admin_token}
X-Tenant-ID: {tenant_id}
Content-Type: application/json
{
"enabled": true
}
List SCIM tokens
GET /api/v1/scim/tokens
Authorization: Bearer {admin_token}
X-Tenant-ID: {tenant_id}
Create SCIM token
POST /api/v1/scim/tokens
Authorization: Bearer {admin_token}
X-Tenant-ID: {tenant_id}
Revoke SCIM token
POST /api/v1/scim/tokens/{id}/revoke
Authorization: Bearer {admin_token}
X-Tenant-ID: {tenant_id}
Next steps
- SAML 2.0 SSO — pair SAML authentication with SCIM provisioning for a complete lifecycle
- Directory Sync — alternative provisioning path for LDAP/AD environments
- User Management — manage users created via SCIM