Skip to main content

Sync users to your LMS

Goal: every person who needs access to an LMS course exists there exactly once, with an up-to-date name and email.

When to create users​

This follows from the user scope decision. The default is on demand: create an LMS user the first time that person needs one, when an enrollment for them is confirmed on an edition that has an LMS course, or when they are assigned as teacher on such an edition. This keeps the LMS clean and avoids accounts for leads and contacts who never take a course.

If you decided to mirror all users, subscribe to user.created as well and create the LMS account straight away.

Identify users by their principal ID​

Every Eduframe user can carry a principal ID: external_identity.principal_id. It is the identifier of that person in the systems around Eduframe, for example the object ID your identity provider issues, and it is what the LMS should store as the external identifier of the account. Use it instead of the numeric Eduframe id:

  • The same key everywhere. Your identity provider, Eduframe and the LMS all know the person by one value, so single sign-on into the LMS lands on the account the integration created.
  • You choose the value. The principal ID is a string you set, so it can follow the convention your organization already uses, such as an employee number or the IdP object ID. Eduframe's id is assigned by Eduframe and only means something inside Eduframe.
  • Independent of email. People change email addresses; the principal ID stays.

Reading the principal ID requires the Manage principal ids feature flag on your environment. It is returned on every user record:

{
"id": 9021,
"first_name": "Edu",
"middle_name": null,
"last_name": "Frame",
"email": "edu.frame@example.com",
"external_identity": {
"principal_id": "e3b0c442-98fc-4d5e-9a1b-7c2f0d1a6b8e"
},
"locale": "en",
"student_number": "X00556667"
}

If a user has no principal ID yet, set one from your middleware. Choose the same value the identity provider and the LMS will use:

POST /api/v1/users/9021/external_identity HTTP/1.1
Host: api.eduframe.nl
Authorization: Bearer <your api key>
Content-Type: application/json

{ "principal_id": "e3b0c442-98fc-4d5e-9a1b-7c2f0d1a6b8e" }

The scope required is relations:modify. New users created through POST /api/v1/users can carry external_identity in the same request.

Fields to map​

From GET /api/v1/users/{id}:

FieldUse it for
external_identity.principal_idExternal identifier on the LMS user and the key you match on.
idEduframe's own identifier. Use it for API calls and to recognize the user in webhook events, not as the LMS external identifier. Keep a mapping from id to principal ID in your middleware, because user.deleted only carries the id and the user can no longer be fetched.
emailLogin name in the LMS, and the fallback key when a user has no principal ID yet.
first_name, middle_name, last_nameDisplay name.
localePreferred language, if your LMS supports per-user language.
student_number, employee_numberOptional secondary identifiers.

Matching and duplicates​

Match on the principal ID first (stored in the LMS external identifier). Fall back to email for accounts that existed before the integration or for users without a principal ID, and when you match by email, write the principal ID to both Eduframe and the LMS so the next event matches directly.

Merged users​

Administrators can merge two duplicate users in Eduframe. All enrollments, orders and other records of the secondary user move to the primary user. Eduframe then sends a user.merged event. Its payload differs from other events: there is no top-level entity, and event_data names both users.

{
"event": "user.merged",
"educator": "drieam-test",
"tenant_id": "29e40df7-4b7c-4a8b-a382-858224237ecc",
"event_data": {
"primary_user_id": 9021,
"secondary_user_id": 9345
}
}

primary_user_id is the user that remains; secondary_user_id is the user that was merged into it. The moved enrollments do not announce themselves separately, so when you handle the event, re-read the primary user's enrollments with GET /api/v1/enrollments?student_id=<primary_user_id> and make sure the primary user has access to every LMS course the secondary user had.

Handling this event is optional. If you do handle it, what you can achieve depends on the merge capabilities of your LMS:

  • The LMS can merge accounts. Merge the LMS account of the secondary user into the account of the primary user, so grades and activity history end up on one account. Moodle offers this through the Merge user accounts admin plugin, which has no API, so the merge itself is a manual or command-line step for the Moodle administrator. Your middleware can prepare it by recording which two accounts belong together.
  • The LMS cannot merge accounts. Deactivate the LMS account of the secondary user and enroll the primary user in its courses. History on the deactivated account stays there. Blackboard Learn has no merge feature, so this is the only option there.
  • Users are managed externally. Users are provisioned into the LMS by another tool, and a merge in Eduframe should not affect that setup. In that case, ignore the event.

In the first two cases, make sure the surviving LMS account carries the principal ID of the primary user. If the LMS knew the person by the secondary user's principal ID, move that value to the primary user with the external identity endpoint so the identity provider, Eduframe and the LMS agree again.

Webhook events to subscribe to​

EventWhat to do
user.updatedFetch the user and update name, email, locale and, if it changed, the external identifier in the LMS.
user.mergedOptional. Merge or deactivate the LMS account of the secondary user, see Merged users.
user.deletedDeactivate the LMS account. Find it through your id to principal ID mapping; the user can no longer be fetched.
user.createdNot needed if you create users on demand. Subscribe to it if you sync all users.