scorm-taking

6 endpoints.

GET/api/scorm-courses/available Bearer token

List the courses the caller can take

Lists the live SCORM courses the caller may take, each with their own attempt state: organization-owned courses of every organization whose directory names them, department-owned courses of departments they hold a role in, and trainers-only courses their scorm:read covers. Needs no permission grant for the first two: the course's audience is the authorization.

Responses

StatusDescriptionBody
200The caller's available courses.AvailableScormCourseList
401The access token is missing or invalid.ErrorResponse
500The database could not be read.ErrorResponse
POST/api/scorm-courses/{course_id}/attempts Bearer token

Launch a course (start or resume an attempt)

Prepares a session of the caller's attempt: resumes the attempt in progress (its saved CMI data seeds the runtime, and its accumulated time rolls forward as the new session's base), or starts attempt n+1 when none is open — immediately with restart: true, which closes the open attempt first. The response carries everything the hosted player needs: the runtime's seed, the launcher page it frames (player_url, on the deployment's SCORM content host — packages never run on the app's own origin), the package's signed launch URL, and the ticket the launcher saves the attempt with. An attempt runs against the package version it was launched with — a resumed attempt keeps its version even after the course's package was replaced; only a fresh attempt starts on the current one. Needs no permission grant: the course's audience is the authorization — organization membership, narrowed to the owning department's role holders for department-owned courses, or scorm:read over the owner for trainers-only courses.

Parameters

NameInTypeRequiredDescription
course_idpathstring (uuid)yesUUID id of the SCORM course.

Request body

application/jsonoptionalLaunchScormCourseRequest
FieldTypeRequiredDescription
restartbooleanno

True closes any attempt in progress and starts a fresh one; the default resumes it.

Responses

StatusDescriptionBody
200The attempt already in progress, resumed.ScormLaunch
201A freshly started attempt.ScormLaunch
401The access token is missing or invalid.ErrorResponse
404No course available to the caller has that id.ErrorResponse
409A concurrent launch is already starting an attempt; retry.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
503File storage is not configured on this deployment, or no SCORM content host is.ErrorResponse
PUT/api/scorm-attempts/{attempt_id} Bearer token

Commit an attempt's CMI data

Saves what the module has reported: the full CMI element map replaces the attempt's saved copy, and the summary the row carries — completion, success, scores, location, accumulated time — is re-derived from it server-side. The first commit that reports the attempt complete also files the result into the learner's records. Call it on every LMSCommit/Commit and on LMSFinish/Terminate; the hosted player saves the same way through PUT /scorm-frame-commits/{commit_ticket}. Only the attempt's own learner may commit; not their attempt is indistinguishable from a missing one.

Parameters

NameInTypeRequiredDescription
attempt_idpathstring (uuid)yesUUID id of the attempt.

Request body

application/jsonrequiredCommitScormAttemptRequest
FieldTypeRequiredDescription
cmiobjectyes

SCORM CMI elements by name, e.g. cmi.core.lesson_status.

api_flavorstring | nullyes

one of "scorm-1.2" | "scorm-2004" | null

terminatedbooleanyes

True once the module has called LMSFinish / Terminate this session.

Responses

StatusDescriptionBody
200The attempt with its freshly derived summary.ScormAttempt
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
404No attempt of the caller's has that id.ErrorResponse
409The attempt is closed; launch the course again for a fresh one.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
GET/api/scorm-content/{ticket}/{asset_path} Public

Serve a file from a course package

Serves one file out of a SCORM course's package zip: the launch page the player's iframe loads, and every asset it references by relative URL. The signed ticket segment is the authorization — POST /scorm-courses/{course_id}/attempts mints it into content_url after checking the caller may take the course — so no bearer token is required (module asset requests cannot carry one). Tickets are scoped to one course and the package version the attempt was launched against, and expire with the session. Served only on the deployment's SCORM content host, never the app's own origin, and only framed by the hosted player.

Parameters

NameInTypeRequiredDescription
ticketpathstringyesSigned content ticket, scoped to one course and package version — the launch response's content_url carries it.
asset_pathpathstringyesPackage-relative path of the file, spanning multiple path segments (the launch page's relative asset URLs resolve here on their own).

Responses

StatusDescriptionBody
200The file's bytes, served with the package entry's own content type.—
400The asset path is missing or malformed.ErrorResponse
403The content ticket is invalid or has expired (relaunch the course), or the request is a service worker's script fetch.ErrorResponse
404The course is gone, no file at that path exists in its package, or this host does not serve SCORM content.ErrorResponse
500The course content could not be served.ErrorResponse
502The course package could not be read from storage.ErrorResponse
POST/api/scorm-frame-commits/{commit_ticket} Public

Commit an attempt's CMI data as the hosted player closes

The same commit as PUT, for the launcher's last save as the tab closes, which it sends with navigator.sendBeacon — a beacon can only POST.

Parameters

NameInTypeRequiredDescription
commit_ticketpathstringyesSigned commit ticket, scoped to one attempt of one learner — the launch response's commit_token.

Request body

application/jsonrequiredCommitScormAttemptRequest
FieldTypeRequiredDescription
cmiobjectyes

SCORM CMI elements by name, e.g. cmi.core.lesson_status.

api_flavorstring | nullyes

one of "scorm-1.2" | "scorm-2004" | null

terminatedbooleanyes

True once the module has called LMSFinish / Terminate this session.

Responses

StatusDescriptionBody
200The attempt with its freshly derived summary.ScormAttempt
400The request body failed validation.ErrorResponse
403The commit ticket is invalid or has expired; relaunch the course.ErrorResponse
404The attempt is gone, or this host does not serve the hosted player.ErrorResponse
409The attempt is closed; launch the course again for a fresh one.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
PUT/api/scorm-frame-commits/{commit_ticket} Public

Commit an attempt's CMI data from the hosted player

Exactly PUT /scorm-attempts/{attempt_id}, authorized by the signed commit ticket in the path instead of a bearer token: the hosted player's launcher page, on the SCORM content host, saves through it on every LMSCommit/Commit, on LMSFinish/Terminate and on its idle autosave. POST /scorm-courses/{course_id}/attempts mints the ticket (commit_token) for the attempt it launches; it is good for that attempt alone and expires with the session. Served only on the SCORM content host.

Parameters

NameInTypeRequiredDescription
commit_ticketpathstringyesSigned commit ticket, scoped to one attempt of one learner — the launch response's commit_token.

Request body

application/jsonrequiredCommitScormAttemptRequest
FieldTypeRequiredDescription
cmiobjectyes

SCORM CMI elements by name, e.g. cmi.core.lesson_status.

api_flavorstring | nullyes

one of "scorm-1.2" | "scorm-2004" | null

terminatedbooleanyes

True once the module has called LMSFinish / Terminate this session.

Responses

StatusDescriptionBody
200The attempt with its freshly derived summary.ScormAttempt
400The request body failed validation.ErrorResponse
403The commit ticket is invalid or has expired; relaunch the course.ErrorResponse
404The attempt is gone, or this host does not serve the hosted player.ErrorResponse
409The attempt is closed; launch the course again for a fresh one.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse