SCIM provisioning (Team Sync)
SCIM 2.0 lets your identity provider (Okta, Entra ID, etc.) automatically create, update, and deactivate People in your modelux projects. When someone joins a team in your IdP, they get a Person record in modelux. When they leave, their Person is deactivated and their API keys are revoked.
SCIM is available on plans that include the security.sso feature. You’ll
typically set it up alongside SAML SSO.
How it works
Each SCIM token is scoped to one internal-persona project. Your IdP provisions People into that project — one token per team/project.
Okta group "ml-platform" → SCIM token → modelux project "ML Platform"
Okta group "eng-tools" → SCIM token → modelux project "Eng Tools"
A SCIM “User” maps to a Person record (an employee identity that API keys attach to), not a dashboard login. Dashboard users are managed by SSO + manual invite.
| SCIM operation | What happens in modelux |
|---|---|
| Create | Creates a Person with source: scim in the token’s project |
PATCH active: false | Sets deactivatedAt, revokes all attached API keys |
PATCH active: true | Clears deactivatedAt (keys stay revoked — mint new ones) |
| PUT (replace) | Updates Person fields; toggles active status with same key-revocation behavior |
| DELETE | Soft-deletes the Person, revokes all attached API keys |
Person attributes
Core SCIM attributes map to Person fields:
| SCIM attribute | Person field |
|---|---|
userName | email (required, immutable after creation) |
displayName | displayName |
externalId | externalId (stable IdP identifier) |
active | controls deactivatedAt |
Additional fields are sent via the modelux Person extension:
urn:modelux:params:scim:schemas:extension:2.0:Person
| Extension attribute | Person field |
|---|---|
team | team |
costCenter | costCenter |
manager | manager |
If your IdP doesn’t populate extension attributes, those fields stay null — you can fill them in manually from the People page.
Setup
1. Create an internal project
People are project-scoped. If you don’t have an internal-persona project yet, create one:
- Dashboard → Projects → Create project → type “Internal tooling”
- Or via MCP:
create_project({ name: "Engineering", persona: "internal" })
2. Create a SCIM token
- Go to Settings → Security, scroll to Team Sync.
- Pick the project from the dropdown.
- Name the token (e.g., “Okta — Engineering”).
- Click Create token and copy the value. It starts with
mlx_scim_and is shown exactly once.
The SCIM endpoint URL is:
https://app.modelux.ai/api/scim/v2
You can also create tokens via MCP:
create_scim_token({ name: "Okta — Engineering", projectId: "<project-id>" })
3. Configure your IdP
Okta
- On your modelux SAML app in Okta → General → App Settings, enable Provisioning → SCIM.
- Base URL:
https://app.modelux.ai/api/scim/v2 - Unique identifier field for users:
userName - Supported provisioning actions: Push New Users, Push Profile Updates. Push Groups is not used.
- Authentication Mode: HTTP Header
- Authorization:
Bearer <your mlx_scim_ token> - Click Test API Credentials — you should get a green checkmark.
On the To App settings, enable Create Users, Update User Attributes, and Deactivate Users.
To send team/costCenter/manager, add custom attribute mappings under
Profile Editor targeting the
urn:modelux:params:scim:schemas:extension:2.0:Person extension.
Microsoft Entra ID
- On your modelux Enterprise app → Provisioning → Get started → Automatic.
- Tenant URL:
https://app.modelux.ai/api/scim/v2 - Secret token: your
mlx_scim_token. - Click Test Connection — Entra should report success.
- Under Mappings → Provision Microsoft Entra ID Users, confirm
userPrincipalNameormailmaps touserName, anddisplayNamemaps correctly. - Set Provisioning Status to On and save.
Entra provisioning cycles every ~40 minutes. Use Provision on demand to test a single user immediately.
Multiple projects
For organizations with multiple teams, create one SCIM token per project:
| IdP group | SCIM token | modelux project |
|---|---|---|
ml-platform | ”Okta — ML Platform” | ML Platform |
eng-tools | ”Okta — Eng Tools” | Eng Tools |
data-team | ”Okta — Data” | Data Pipeline |
Each token provisions into its own project. The same email can exist as a Person in multiple projects — each project tracks their API keys and spend independently.
When someone is removed from an IdP group, only their Person record in that group’s project is deactivated. If they’re in multiple groups/projects, the others are unaffected.
API keys
SCIM creates Person records but does not auto-mint API keys. After a Person is provisioned, create keys for them:
- Dashboard → project’s API keys → Create key → select the Person
- MCP:
create_api_key({ projectId: "...", name: "alex-dev", personId: "..." }) - Management API:
POST /manage/v1/keyswithpersonId
When a Person is deactivated or deleted via SCIM, all their attached API keys are revoked immediately.
Deactivation vs deletion
Deactivation (PATCH active: false) keeps the Person record but marks
it inactive. Revokes API keys. The Person can be reactivated later — but
revoked keys stay revoked; mint new ones.
Deletion (DELETE /Users/<id>) soft-deletes the Person (deletedAt
set). Also revokes keys. The Person won’t appear in lists or SCIM queries.
The record stays in the database for audit purposes.
Filtering
The SCIM list endpoint supports two filter expressions:
GET /api/scim/v2/Users?filter=userName eq "alex@acme.com"
GET /api/scim/v2/Users?filter=externalId eq "okta-abc123"
Other filter expressions return an empty result set (harmless — the IdP will fall through to creating the user, and the uniqueness constraint deduplicates).
Testing
- Create a test user in your IdP and assign them to the modelux app/group.
- Trigger provisioning. They should appear on the People page for the token’s project within seconds (Okta) or minutes (Entra).
- Deactivate them in the IdP. Their Person should show as deactivated and any attached API keys should be revoked.
- Reactivate and confirm they reappear as active (keys stay revoked).
Auditing
Every SCIM mutation is logged. Check Settings → Audit Log filtered by
resource type person to see SCIM-driven changes.