SCIM provisioning
mngd speaks SCIM 2.0 (RFC 7643 + 7644), so any IdP that supports SCIM — Okta, Azure AD / Entra ID, Google Workspace via third-party connectors, OneLogin, Rippling, etc. — can push user and group changes to mngd automatically. On deprovisioning, deleted users are soft-deleted and role assignments cleared.
Pair SCIM with SSO for the full story: SSO handles login, SCIM handles the user + role lifecycle. You can run either one on its own, but together they mean new hires can sign in the minute your IdP creates them and offboarding revokes access everywhere in one step.
Generating the SCIM credentials
Section titled “Generating the SCIM credentials”Go to Settings → Identity → SCIM Provisioning. Click Generate token (or Rotate if one already exists).
You’ll get two values to paste into your IdP:
- Base URL —
https://app.mngd.app/scim/v2 - Bearer token — shown exactly once, starts with
scim_. Copy it into your IdP’s SCIM configuration as the bearer/API token. mngd stores only a SHA-256 hash; if you lose it, rotate and reconfigure.
Rotate the token anytime. The old value stops working immediately; reconfigure your IdP with the new one.
Revoke via the Revoke button if you need to cut SCIM access entirely — existing users stay, but the IdP can no longer create, modify, or deactivate them over SCIM.
What’s exposed
Section titled “What’s exposed”Endpoints under https://app.mngd.app/scim/v2:
| Resource | Methods |
|---|---|
/ServiceProviderConfig | GET — capability discovery |
/Schemas | GET — User + Group schemas |
/Users | GET, POST, GET /{id}, PUT /{id}, PATCH /{id}, DELETE /{id} |
/Groups | GET, POST, GET /{id}, PUT /{id}, PATCH /{id}, DELETE /{id} |
All requests need Authorization: Bearer <scim_...>.
User attributes
Section titled “User attributes”| Attribute | Required | Notes |
|---|---|---|
userName | required | Must be a valid email; mngd uses it as the primary key within the org |
emails[].value | recommended | Primary email. primary: true honored |
displayName | optional | Shown in the admin UI |
name.formatted / name.givenName / name.familyName | optional | Stored; not currently surfaced |
externalId | optional | Stable IdP-side ID; useful when emails change |
active | optional (default true) | false soft-deletes the user |
roles[].value | optional | mngd role (owner, admin, operator, viewer) — sets role directly, bypassing group mapping |
Group attributes
Section titled “Group attributes”| Attribute | Required | Notes |
|---|---|---|
displayName | required | Exact-match (case-sensitive) against your group→role mappings |
externalId | optional | IdP group ID |
members[] | optional | Each entry { "value": "<mngd user id>", "display": "<email>" } |
PATCH operation support
Section titled “PATCH operation support”Full SCIM 2.0 PATCH — Add, Replace, Remove — with paths:
{ "op": "replace", "path": "active", "value": false }{ "op": "replace", "path": "displayName", "value": "New Name" }{ "op": "replace", "path": "roles", "value": [{ "value": "admin" }] }{ "op": "add", "path": "members", "value": [{ "value": "<user-id>" }] }{ "op": "remove", "path": "members", "value": [{ "value": "<user-id>" }] }Object-valued replace also works for multi-field updates:
{ "op": "replace", "value": { "active": false, "displayName": "Updated" } }Mapping IdP groups to mngd roles
Section titled “Mapping IdP groups to mngd roles”This is how SSO users get promoted beyond the default viewer role. Without it, every new JIT-provisioned user starts at viewer and needs manual promotion.
On Settings → Identity → SCIM Group → Role Mappings, create one
row per IdP group you want to map. Match your IdP group’s
displayName exactly (case-sensitive) to an mngd role.
| IdP group name | mngd role |
|---|---|
mngd-owners | owner |
mngd-admins | admin |
mngd-ops | operator |
mngd-viewers | viewer |
When the IdP pushes a group membership change via SCIM:
- Add to a mapped group — user’s role is upgraded to the mapped role if it’s higher-privilege than what they have. mngd never downgrades a user on group removal alone — a user whose role was manually set stays at that level until explicitly changed.
- Remove from a mapped group — any granular role assignments granted via SCIM for that group are cleared.
- User deleted over SCIM — all SCIM-granted role assignments are revoked and the user is soft-deleted.
Provisioning behaviour
Section titled “Provisioning behaviour”| Event | SCIM operation | Effect in mngd |
|---|---|---|
| Create user | POST /Users | New user created, role from roles[] if present, else from group mappings, else viewer |
| Deactivate user | PUT or PATCH with active: false | Soft delete — user loses access but record is preserved for audit |
| Rename user | PATCH displayName | Display name updated; no auth impact |
| Delete user | DELETE /Users/{id} | Hard delete + audit log USER_DEPROVISIONED; all role assignments cleared |
| Create group | POST /Groups | Group created in mngd’s SCIM mirror — doesn’t affect roles until mapped |
| Add member | PATCH group with add members | Evaluated against group→role mappings; affected users’ roles updated |
| Remove member | PATCH group with remove members | SCIM-granted assignments for that user + group cleared |
Pagination: startIndex is 1-based, count defaults to 50, max
100. No bulk operations endpoint.
Filter syntax
Section titled “Filter syntax”Standard SCIM 2.0 filter expressions on list endpoints:
GET /Users?filter=userName eq "[email protected]"GET /Users?filter=active eq trueGET /Groups?filter=displayName eq "mngd-admins"Known limitations
Section titled “Known limitations”- Group name match is case-sensitive.
mngd-Adminsandmngd-adminsare different groups to mngd. - No bulk endpoint. IdPs that batch SCIM calls will make N individual requests — works fine, just slower for large changes.
- Attribute map not processed. The
attribute_mapcolumn exists for future custom-claim handling but isn’t read today. The attributes in the table above are the full set mngd consumes. roles[]on create vs group mapping — if an IdP sends bothrolesand group membership that both resolve to mngd roles, theroles[]value wins. This surprises some IdPs that drive everything via groups; setroles[]explicitly or not at all.- Soft-delete only on
active: false. Hard delete requires aDELETE /Users/{id}request — not all IdPs send this on offboarding.