scorm-taking
6 endpoints.
/api/scorm-courses/available Bearer tokenList 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
| Status | Description | Body |
|---|---|---|
| 200 | The caller's available courses. | AvailableScormCourseList |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 500 | The database could not be read. | ErrorResponse |
/api/scorm-courses/{course_id}/attempts Bearer tokenLaunch 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| course_id | path | string (uuid) | yes | UUID id of the SCORM course. |
| Field | Type | Required | Description |
|---|---|---|---|
| restart | boolean | no | True closes any attempt in progress and starts a fresh one; the default resumes it. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The attempt already in progress, resumed. | ScormLaunch |
| 201 | A freshly started attempt. | ScormLaunch |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 404 | No course available to the caller has that id. | ErrorResponse |
| 409 | A concurrent launch is already starting an attempt; retry. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
| 503 | File storage is not configured on this deployment, or no SCORM content host is. | ErrorResponse |
/api/scorm-attempts/{attempt_id} Bearer tokenCommit 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| attempt_id | path | string (uuid) | yes | UUID id of the attempt. |
| Field | Type | Required | Description |
|---|---|---|---|
| cmi | object | yes | SCORM CMI elements by name, e.g. cmi.core.lesson_status. |
| api_flavor | string | null | yes | one of "scorm-1.2" | "scorm-2004" | null |
| terminated | boolean | yes | True once the module has called LMSFinish / Terminate this session. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The attempt with its freshly derived summary. | ScormAttempt |
| 400 | The request body failed validation. | ErrorResponse |
| 401 | The access token is missing or invalid. | ErrorResponse |
| 404 | No attempt of the caller's has that id. | ErrorResponse |
| 409 | The attempt is closed; launch the course again for a fresh one. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/scorm-content/{ticket}/{asset_path} PublicServe 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| ticket | path | string | yes | Signed content ticket, scoped to one course and package version — the launch response's content_url carries it. |
| asset_path | path | string | yes | Package-relative path of the file, spanning multiple path segments (the launch page's relative asset URLs resolve here on their own). |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The file's bytes, served with the package entry's own content type. | — |
| 400 | The asset path is missing or malformed. | ErrorResponse |
| 403 | The content ticket is invalid or has expired (relaunch the course), or the request is a service worker's script fetch. | ErrorResponse |
| 404 | The course is gone, no file at that path exists in its package, or this host does not serve SCORM content. | ErrorResponse |
| 500 | The course content could not be served. | ErrorResponse |
| 502 | The course package could not be read from storage. | ErrorResponse |
/api/scorm-frame-commits/{commit_ticket} PublicCommit 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| commit_ticket | path | string | yes | Signed commit ticket, scoped to one attempt of one learner — the launch response's commit_token. |
| Field | Type | Required | Description |
|---|---|---|---|
| cmi | object | yes | SCORM CMI elements by name, e.g. cmi.core.lesson_status. |
| api_flavor | string | null | yes | one of "scorm-1.2" | "scorm-2004" | null |
| terminated | boolean | yes | True once the module has called LMSFinish / Terminate this session. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The attempt with its freshly derived summary. | ScormAttempt |
| 400 | The request body failed validation. | ErrorResponse |
| 403 | The commit ticket is invalid or has expired; relaunch the course. | ErrorResponse |
| 404 | The attempt is gone, or this host does not serve the hosted player. | ErrorResponse |
| 409 | The attempt is closed; launch the course again for a fresh one. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |
/api/scorm-frame-commits/{commit_ticket} PublicCommit 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| commit_ticket | path | string | yes | Signed commit ticket, scoped to one attempt of one learner — the launch response's commit_token. |
| Field | Type | Required | Description |
|---|---|---|---|
| cmi | object | yes | SCORM CMI elements by name, e.g. cmi.core.lesson_status. |
| api_flavor | string | null | yes | one of "scorm-1.2" | "scorm-2004" | null |
| terminated | boolean | yes | True once the module has called LMSFinish / Terminate this session. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The attempt with its freshly derived summary. | ScormAttempt |
| 400 | The request body failed validation. | ErrorResponse |
| 403 | The commit ticket is invalid or has expired; relaunch the course. | ErrorResponse |
| 404 | The attempt is gone, or this host does not serve the hosted player. | ErrorResponse |
| 409 | The attempt is closed; launch the course again for a fresh one. | ErrorResponse |
| 500 | The database could not be reached, or the write failed. | ErrorResponse |