IntegrationsSCIM — User Provisioning

SCIM user provisioning

EmbayLMS supports SCIM 2.0 (System for Cross-domain Identity Management) so your identity provider — Okta, Microsoft Entra ID (Azure AD), or any SCIM-2.0 client — can create, update, and deactivate EmbayLMS user accounts automatically, keeping them in sync with your HR system.

When an employee is onboarded in your IdP, the IdP provisions an EmbayLMS account. When their attributes change (name, role), the IdP pushes the update. When they are offboarded, the IdP deactivates the account in EmbayLMS — the learning record is preserved, not deleted.

SCIM vs. SSO: SCIM manages accounts (provisioning). SAML/OIDC manages logins (authentication). They are independent — you can run either alone, but most organizations run SCIM alongside SAML or OIDC so accounts are both auto-created and SSO-enabled.

Base endpoint

SCIM is served per-tenant on your own subdomain. The base URL is:

https://<your-tenant>.embaylms.com/api/v1/scim/v2

Two resource endpoints are implemented:

EndpointResource
/api/v1/scim/v2/UsersUser provisioning
/api/v1/scim/v2/GroupsGroup provisioning

All requests authenticate with a Bearer token (see Step 1) and the tenant is resolved automatically from the subdomain.

Step 1 — Generate a SCIM bearer token

  1. In EmbayLMS, go to Admin → Settings → User Management → SCIM.
  2. Click Create token, enter a label (e.g. “Okta production”), and create it.
  3. The token is shown only once in a reveal banner. Copy it immediately — it cannot be retrieved again. Only a short prefix is stored for identification.
  4. The page also shows the SCIM base path (/api/v1/scim/v2) for reference.

You can create multiple tokens (e.g. one per IdP) and revoke any of them at any time from the same page; the list shows each token’s label, prefix, creation date, and last-used date. Revoking a token immediately stops provisioning for any IdP using it.

Tokens are stored as a SHA-256 hash. EmbayLMS never stores or displays the raw token after creation.

Step 2 — Supported operations and attributes

Users (/Users)

OperationMethodBehavior
List / filterGETLists active users; supports startIndex / count paging and the filter userName eq "user@example.com"
CreatePOSTProvisions a new user (or updates a match — see Matching)
ReadGET /Users/{id}Returns one user
ReplacePUTReplaces a user’s attributes
UpdatePATCHPartial update (e.g. set active)
DeactivateDELETE / active=falseDeactivates the user (see Deprovisioning)

User attribute mapping — SCIM attributes map to EmbayLMS user fields as follows:

SCIM attributeEmbayLMS fieldNotes
userNameEmailMust be a valid email address; used as the primary identifier
name.givenNameFirst nameDefaults to Unknown if omitted
name.familyNameLast nameDefaults to Unknown if omitted
activeAccount statustrue = active, false = deactivated (default true)
externalIdSCIM external IDThe IdP’s stable ID — used for matching on re-sync
roles[0].valueRoleFirst role value; one of learner, author, manager, admin. Any other value falls back to learner

Groups (/Groups)

OperationMethodBehavior
ListGETLists groups with members; supports startIndex / count paging
CreatePOSTProvisions a group with its members
ReplacePUTReplaces the group’s display name and full member list

Group attribute mapping:

SCIM attributeEmbayLMS fieldNotes
displayNameGroup nameRequired
externalIdSCIM external IDUsed for matching; auto-generated if the IdP omits it
members[].valueMember user IDsThe EmbayLMS user id of each member

Step 3 — Matching logic and deprovisioning

Matching (create vs. update). On a user POST, EmbayLMS first looks for an existing user by externalId. If one is found, that user is updated in place (email, name, role, active) rather than duplicated. If no externalId match exists, it checks for an existing user with the same email — if that email is already taken, the request returns 409 Conflict; otherwise a new user is created. Groups follow the same pattern, matched by externalId.

Recommendation: always send a stable externalId from your IdP. It is the key that lets EmbayLMS recognize the same person across syncs (including after an email change), which prevents duplicate accounts.

Deprovisioning. EmbayLMS does not hard-delete users via SCIM. When your IdP unassigns or deactivates a user, send active: false (via PATCH, PUT, or DELETE). The account is deactivated: the user can no longer sign in, but their completions, certificates, and transcript are retained for compliance. Re-sending active: true reactivates the same account with its history intact.

Audit. Every SCIM create and update is written to the EmbayLMS audit log (actor system, role scim) for SOC 2 evidence.

Step 4 — Worked example: configure Okta

  1. In the Okta Admin Console, go to Applications → Browse App Catalog, add a SCIM 2.0 Test App (or your existing EmbayLMS SAML app if it supports provisioning), then open its Provisioning tab and click Configure API Integration.

  2. Enter the SCIM connector settings:

    Okta fieldValue
    SCIM connector base URLhttps://<your-tenant>.embaylms.com/api/v1/scim/v2
    Unique identifier field for usersuserName
    Authentication ModeHTTP Header
    AuthorizationBearer <token from Step 1>
    Supported provisioning actionsPush New Users, Push Profile Updates, Push Groups
  3. Click Test API Credentials — Okta calls GET /Users to verify the token.

  4. Under Provisioning → To App, enable Create Users, Update User Attributes, and Deactivate Users.

  5. Map Okta profile attributes to SCIM: userName → email, givenName, familyName, and (optionally) a roles mapping to one of learner, author, manager, admin.

  6. Assign people/groups to the app. Okta provisions them into EmbayLMS; unassigning a user sends active: false, which deactivates the account.

Entra ID (Azure AD): the flow is equivalent — add the Enterprise application → Provisioning, set Provisioning Mode to Automatic, paste the same base URL as the Tenant URL and the token as the Secret Token, then Test Connection and start provisioning.

Configuration reference

FieldWhereValue
SCIM base URLYour IdP’s SCIM apphttps://<your-tenant>.embaylms.com/api/v1/scim/v2
Bearer tokenAdmin → Settings → User Management → SCIM → Create tokenShown once; copy immediately
Unique user identifierYour IdPuserName (email)
Stable match keyYour IdPexternalId (strongly recommended)
Role attributeYour IdP roles[0].valuelearner | author | manager | admin
PagingQuery stringstartIndex (1-based), count (max 200)
User filterQuery stringuserName eq "user@example.com"

Troubleshooting

SymptomCause / fix
Test credentials / connection fails with 401The bearer token is wrong, revoked, or the tenant is not active. Re-check the Authorization header is Bearer <token> and generate a fresh token if needed.
401 even with a valid-looking tokenThe request must hit your tenant subdomain (<your-tenant>.embaylms.com) — the tenant is resolved from the host. A bare apex/platform URL will not authenticate.
Create user returns 409 ConflictA user with that userName (email) already exists but has a different/absent externalId. Set a matching externalId in your IdP so EmbayLMS updates the existing account instead of creating a new one.
userName must be a valid email address (400)userName must contain @. Map your IdP’s email attribute to userName.
User provisioned as learner despite a different roleThe roles[0].value was missing or not one of learner/author/manager/admin; EmbayLMS falls back to learner. Fix the role mapping in your IdP.
Deactivated user still appears in reportsExpected — deactivation preserves the learning record. The user cannot log in. See Deprovisioning.
Duplicate accounts after an email changeThe IdP did not send a stable externalId, so the new email created a new account. Configure externalId mapping and merge the duplicate via the transcript tools in User Management.