API ReferenceEnrollments

Enrollments

An enrollment represents a single learner assigned to a single course. Reading (GET), creating (POST), bulk-creating (POST /enrollments/bulk), fetching one (GET /enrollments/{id}), reading its progress (GET /enrollments/{id}/progress), updating (PATCH /enrollments/{id}, e.g. the due date), and unenrolling (DELETE /enrollments/{id}) are all available. Reads need the read scope, creates and updates the write scope, and unenroll the admin scope.


The Enrollment Object

{
  "id": "d6e5f4a3-7b8c-9012-defa-123456789012",
  "user_id": "a3f2c1d0-4e5b-6789-abcd-ef0123456789",
  "course_id": "e7f6a5b4-8c9d-0123-efab-234567890123",
  "status": "active",
  "due_date": "2026-07-01T00:00:00Z",
  "completed_at": null,
  "source": "native",
  "created_at": "2026-05-01T08:00:00Z"
}
FieldTypeNotes
iduuidEnrollment UUID
user_iduuidThe enrolled learner
course_iduuidThe course
statusstringSee status values below
due_dateISO 8601 | nullDeadline for completion, if set
completed_atISO 8601 | nullWhen the course was completed
sourcestringnative or import (Switcher historical data)
created_atISO 8601When the enrollment was created

Enrollment status values:

StatusDescription
activeEnrollment is in effect — the learner can take the course
completedCourse finished
droppedLearner was unenrolled / dropped the course
expiredEnrollment validity window has passed
waitlistedWaiting for a seat (session/capacity-limited courses)
pending_approvalAwaiting manager approval

Endpoints

List Enrollments

GET /api/v1/enrollments

Returns a paginated list of enrollments across the tenant, most recently created first.

Authentication required: API key with the read scope

Query Parameters

ParameterTypeRequiredDescription
pageintegerNoDefault: 1
per_pageintegerNoDefault: 50, max: 200
user_idUUIDNoFilter by user
course_idUUIDNoFilter by course
statusstringNoFilter: active, completed, dropped, expired, waitlisted, pending_approval

Example Request

curl "https://{your-subdomain}.embaylms.com/api/v1/enrollments?status=active&course_id=e7f6a5b4-8c9d-0123-efab-234567890123" \
  -H "Authorization: Bearer ems_live_0000000000000000000000000000"

Example Response

{
  "data": [
    {
      "id": "d6e5f4a3-7b8c-9012-defa-123456789012",
      "user_id": "a3f2c1d0-4e5b-6789-abcd-ef0123456789",
      "course_id": "e7f6a5b4-8c9d-0123-efab-234567890123",
      "status": "active",
      "due_date": "2026-05-01T00:00:00Z",
      "completed_at": null,
      "source": "native",
      "created_at": "2026-04-01T08:00:00Z"
    }
  ],
  "meta": { "page": 1, "per_page": 50, "total": 23 },
  "error": null
}

Common Errors

Errors use the standard envelope with a numeric error.code matching the HTTP status — see Errors.

HTTP StatusDescription
401Missing or invalid API key
403Key lacks the read scope, or the API is not included in your plan
429Rate limit or monthly usage cap exceeded — see Rate Limits

Available. POST /enrollments (create), POST /enrollments/bulk, GET /enrollments/{id}, and DELETE /enrollments/{id} (unenroll) shipped in the first LMS-539 write tranche. PATCH /enrollments/{id} (change due date), GET /enrollments/{id}/progress, and the additional GET /enrollments list filters (group_id, due_before, due_after, created_after, sort_by, sort_order) shipped in LMS-574 and are now live.

Additional List Filters

The following GET /api/v1/enrollments query parameters are available:

ParameterTypeDescription
group_idUUIDFilter enrollments for users in a specific group
due_beforeISO 8601Filter enrollments with due date before this timestamp
due_afterISO 8601Filter enrollments with due date after this timestamp
created_afterISO 8601Filter enrollments created after this timestamp
sort_bystringenrolled_at, due_date, completed_at. Default: enrolled_at
sort_orderstringasc or desc. Default: desc

The write API also extends the Enrollment object with progress_percent, score, pass_fail, enrolled_at, started_at, certificate_id, and updated_at fields, as shown in the examples below.


Create Enrollment

POST /api/v1/enrollments

Enrolls a user in a course through the same enrollment engine as the in-app flow: the enrollment window, seat cap (waitlisting when enabled), manager-approval requirement (status pending_approval), and prerequisites are all enforced. The course must be published. A live enrollment (active, completed, waitlisted, or pending approval) returns 409; a previously dropped or expired enrollment is reactivated with a clean slate. A confirmation notification is always sent to the learner.

Authentication required: write scope

Request Body

FieldTypeRequiredDescription
user_idUUIDYesUser to enroll
course_idUUIDYesCourse to enroll the user in
due_dateISO 8601NoDeadline for completion

Example Request

curl -X POST https://{your-subdomain}.embaylms.com/api/v1/enrollments \
  -H "Authorization: Bearer ems_live_0000000000000000000000000000" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "a3f2c1d0-4e5b-6789-abcd-ef0123456789",
    "course_id": "e7f6a5b4-8c9d-0123-efab-234567890123",
    "due_date": "2026-09-01T00:00:00Z"
  }'

Example Response

{
  "data": {
    "id": "5e6f7a8b-9c0d-1234-efab-234567890123",
    "user_id": "a3f2c1d0-4e5b-6789-abcd-ef0123456789",
    "course_id": "e7f6a5b4-8c9d-0123-efab-234567890123",
    "status": "active",
    "due_date": "2026-09-01T00:00:00Z",
    "created_at": "2026-06-05T10:30:00Z"
  },
  "meta": null,
  "error": null
}

HTTP Status: 201 Created

status is active, pending_approval (the course requires manager approval), or waitlisted (the course is full and has a waitlist). Progress and completion details live on Get Enrollment Progress.

Common Errors

HTTP StatusDescription
404User or course does not exist
409User already has a live enrollment (active/completed/waitlisted/pending approval) in this course
422Enrollment rejected: window closed, course full with no waitlist, prerequisites incomplete, or an ILT series selection is required (enroll in-app)
422Course is not in published status

Get Enrollment

GET /api/v1/enrollments/{id}

Returns a single enrollment by UUID.

Authentication required: read scope

Path Parameters

ParameterTypeRequiredDescription
idUUIDYesEnrollment UUID

Example Request

curl "https://{your-subdomain}.embaylms.com/api/v1/enrollments/d6e5f4a3-7b8c-9012-defa-123456789012" \
  -H "Authorization: Bearer ems_live_0000000000000000000000000000"

Example Response

Returns the full enrollment object (see The Enrollment Object).


Update Enrollment

PATCH /api/v1/enrollments/{id}

Updates mutable fields on an enrollment. Currently supports updating the due date.

Authentication required: write scope

Path Parameters

ParameterTypeRequiredDescription
idUUIDYesEnrollment UUID

Request Body

FieldTypeRequiredDescription
due_dateISO 8601 or nullNoNew due date. Pass null to remove the due date

Example Request

curl -X PATCH "https://{your-subdomain}.embaylms.com/api/v1/enrollments/d6e5f4a3-7b8c-9012-defa-123456789012" \
  -H "Authorization: Bearer ems_live_0000000000000000000000000000" \
  -H "Content-Type: application/json" \
  -d '{ "due_date": "2026-10-01T00:00:00Z" }'

Example Response

Returns the updated enrollment object.


Unenroll

DELETE /api/v1/enrollments/{id}

Unenrolls a user from a course. If the course has been completed, the enrollment cannot be deleted — it becomes a permanent part of the user’s transcript. Use this only to remove enrollments that have not yet been completed.

Authentication required: admin scope

Path Parameters

ParameterTypeRequiredDescription
idUUIDYesEnrollment UUID

Example Request

curl -X DELETE "https://{your-subdomain}.embaylms.com/api/v1/enrollments/d6e5f4a3-7b8c-9012-defa-123456789012" \
  -H "Authorization: Bearer ems_live_0000000000000000000000000000"

HTTP Status: 204 No Content

Common Errors

HTTP StatusDescription
422Enrollment is already completed and cannot be deleted

Bulk Enroll

POST /api/v1/enrollments/bulk

Enrolls up to 500 users in one or more courses in a single request. Every row runs the full enrollment engine independently; rows that fail (already enrolled, course full, prerequisites, etc.) are reported per-row in errors[] with the batch returning 207 Multi-Status — the remaining rows still succeed. Confirmation notifications are sent per enrollment.

Authentication required: write scope

Request Body

FieldTypeRequiredDescription
enrollmentsEnrollment[]YesArray of enrollment objects (max 500)

Each item in enrollments:

FieldTypeRequiredDescription
user_idUUIDYesUser to enroll
course_idUUIDYesCourse to enroll in
due_dateISO 8601NoDeadline for completion

Example Request

curl -X POST https://{your-subdomain}.embaylms.com/api/v1/enrollments/bulk \
  -H "Authorization: Bearer ems_live_0000000000000000000000000000" \
  -H "Content-Type: application/json" \
  -d '{
    "enrollments": [
      {
        "user_id": "a3f2c1d0-4e5b-6789-abcd-ef0123456789",
        "course_id": "e7f6a5b4-8c9d-0123-efab-234567890123",
        "due_date": "2026-09-01T00:00:00Z"
      },
      {
        "user_id": "c5d4e3f2-6a7b-8901-cdef-012345678901",
        "course_id": "e7f6a5b4-8c9d-0123-efab-234567890123",
        "due_date": "2026-09-01T00:00:00Z"
      }
    ]
  }'

Example Response

{
  "data": {
    "created": 2,
    "skipped": 0,
    "errors": []
  },
  "meta": null,
  "error": null
}

HTTP Status: 207 Multi-Status on partial errors; 201 when all succeed.


Get Enrollment Progress

GET /api/v1/enrollments/{id}/progress

Returns detailed progress data for an enrollment — module-level completion, scores, and time spent.

Authentication required: read scope

Path Parameters

ParameterTypeRequiredDescription
idUUIDYesEnrollment UUID

Example Request

curl "https://{your-subdomain}.embaylms.com/api/v1/enrollments/d6e5f4a3-7b8c-9012-defa-123456789012/progress" \
  -H "Authorization: Bearer ems_live_0000000000000000000000000000"

Example Response

{
  "data": {
    "enrollment_id": "d6e5f4a3-7b8c-9012-defa-123456789012",
    "overall_progress_percent": 65,
    "time_spent_seconds": 1842,
    "last_activity_at": "2026-06-04T11:20:00Z",
    "modules": [
      {
        "module_id": "3c4d5e6f-7a8b-9012-cdef-012345678901",
        "module_title": "Introduction to WHMIS",
        "status": "completed",
        "score": null,
        "time_spent_seconds": 920,
        "completed_at": "2026-05-10T10:15:00Z"
      },
      {
        "module_id": "4d5e6f7a-8b9c-0123-defa-123456789012",
        "module_title": "Final Assessment",
        "status": "not_started",
        "score": null,
        "time_spent_seconds": 0,
        "completed_at": null
      }
    ]
  },
  "meta": null,
  "error": null
}