scorm

12 endpoints.

GET/api/scorm-courses/{course_id}/attempts Bearer token

List a course's attempts

Lists every learner's attempts of one course, newest first, one page at a time — each joined with the learner's current profile. Requires scorm:read over the course's owner.

Parameters

NameInTypeRequiredDescription
course_idpathstring (uuid)yesUUID id of the SCORM course.
limitqueryintegernoPage size, 1-200. Defaults to 50.
cursorquerystringnoOpaque cursor from a previous page's next_cursor.

Responses

StatusDescriptionBody
200One page of the course's attempts.ScormCourseAttemptList
400The cursor is not one this API issued.ErrorResponse
401The access token is missing or invalid.ErrorResponse
404No visible course has that id.ErrorResponse
500The database could not be read.ErrorResponse
POST/api/scorm-courses/uploads Bearer token

Mint an upload ticket for a SCORM package

Issues a presigned upload URL for one SCORM package (.zip), bypassing the request-body limit by sending the bytes straight to the private blob store. The signed ticket pins a server-chosen pathname, zip content types and the package size cap. The staged upload becomes a course only through POST /scorm-courses, which validates the package first. Requires scorm:write over the intended owner — the organization, or the owning department within it when one is named.

Request body

application/jsonrequiredScormPackageUploadRequest
FieldTypeRequiredDescription
orgstringyes

Organization UUID id or slug the course will belong to.

at least 1 character

departmentstringno

UUID id or slug of the owning department within the organization; omit for a course owned by the organization directly.

at least 1 character

file_namestringyes

1–255 characters

size_bytesintegeryes

Declared package size; the upload token enforces the cap.

maximum 314572800

Responses

StatusDescriptionBody
201The presigned upload ticket.ScormPackageUploadTicket
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller does not hold scorm:write over the intended owner.ErrorResponse
404No visible organization has that id or slug, or the department is not one of the organization's own.ErrorResponse
500The upload ticket could not be issued.ErrorResponse
503File storage is not configured on this deployment.ErrorResponse
GET/api/scorm-courses Bearer token

List SCORM courses

Lists the hosted SCORM courses the caller's scorm:read scope covers, newest first, optionally filtered to one organization or one owning department within it. Learners list what they can take through GET /scorm-courses/available instead.

Parameters

NameInTypeRequiredDescription
orgquerystringnoOrganization UUID id or slug to filter by (and to resolve slug refs in).
departmentquerystringnoDepartment UUID id or slug, resolved within org (which is then required).
include_archivedquerystringnoInclude archived rows. Defaults to false.

Responses

StatusDescriptionBody
200The visible courses.ScormCourseList
400The department filter was given without an org filter.ErrorResponse
401The access token is missing or invalid.ErrorResponse
404No visible organization has that id or slug, or the department is not one of the organization's own.ErrorResponse
500The database could not be read.ErrorResponse
POST/api/scorm-courses Bearer token

Register an uploaded package as a course

Completes a package upload: validates the staged zip (it must contain an imsmanifest.xml whose launch resource exists in the archive), captures the launch path, SCORM version, manifest objectives and mastery score, and creates the course — owned by the organization, or by the owning department named within it, tagged with the subjects named, and open to trainees unless audience says trainers only. Requires scorm:write over that owner. An invalid package is rejected and its staged blob deleted.

Request body

application/jsonrequiredCreateScormCourseRequest
FieldTypeRequiredDescription
orgstringyes

Organization UUID id or slug the course belongs to.

at least 1 character

departmentstringno

UUID id or slug of the owning department within the organization; omit for a course owned by the organization directly. Ownership scopes administration and limits taking the course to the department's role holders.

at least 1 character

pathnamestringyes

matches ^scorm-courses\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/[^/]{1,100}$

file_namestringyes

1–255 characters

namestringno

Defaults to the title in the package manifest, then the file name.

at most 200 characters

descriptionstringno

at most 5000 characters

audiencestringno

Defaults to trainees: open to everyone the course's ownership admits.

one of "trainees" | "trainers"

subject_matter_idsarray of string (uuid)no

Subjects of the course's organization to tag it with; completion records are filed under all of them. Omit for an untagged course.

at most 50 items

Responses

StatusDescriptionBody
201The registered course.ScormCourse
400The request body failed validation, no upload exists at the pathname, or the package is not a runnable SCORM module.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller does not hold scorm:write over the intended owner.ErrorResponse
404No visible organization has that id or slug, or the department or a subject matter is not the organization's own.ErrorResponse
409That uploaded package is already registered.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
503File storage is not configured on this deployment.ErrorResponse
PUT/api/scorm-courses/{course_id}/subjects Bearer token

Replace a course's subject tags

Sets the complete set of subjects the course — and every completion record it reports from now on — is filed under. Records already written keep their tags. Subjects of the course's own organization only. Requires scorm:write over the course's owner.

Parameters

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

Request body

application/jsonrequiredSetScormCourseSubjectsRequest
FieldTypeRequiredDescription
subject_matter_idsarray of string (uuid)yes

Replaces the course's subject-matter tags.

at most 50 items

Responses

StatusDescriptionBody
200The course's subjects after the change, alphabetically.array of ScormCourseSubject
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller does not hold scorm:write over the course's owner.ErrorResponse
404No visible course has that id, or a subject is not the organization's own.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
POST/api/scorm-courses/{course_id}/package-uploads Bearer token

Mint an upload ticket for a replacement package

Issues a presigned upload URL for the zip that will replace this course's package, exactly as POST /scorm-courses/uploads does for a new course: the bytes go straight to the private blob store under a server-chosen pathname. The staged upload becomes the course's package only through PUT /scorm-courses/{course_id}/package, which validates it first. Requires scorm:write over the course's owner.

Parameters

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

Request body

application/jsonrequiredScormPackageReplacementUploadRequest
FieldTypeRequiredDescription
file_namestringyes

1–255 characters

size_bytesintegeryes

Declared package size; the upload token enforces the cap.

maximum 314572800

Responses

StatusDescriptionBody
201The presigned upload ticket.ScormPackageUploadTicket
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller does not hold scorm:write over the course's owner.ErrorResponse
404No visible course has that id.ErrorResponse
500The upload ticket could not be issued.ErrorResponse
503File storage is not configured on this deployment.ErrorResponse
PUT/api/scorm-courses/{course_id}/package Bearer token

Replace the course's package

Makes a staged upload the course's next package version: the zip is validated like a new registration (an imsmanifest.xml whose launch resource exists), and its launch path, SCORM version, objectives and mastery score become what fresh attempts run. The course keeps its id, name, subjects, audience and every attempt on record, so nothing that points at it — proof rules, pathways, QR codes — changes; an attempt in progress keeps running, and resumes on, the version it was launched with, and every earlier version's package stays stored for that and for the record. requires_recertification decides what the replacement means for learners: true means only completions of this version or later satisfy scorm_course_complete rules from now on, so everyone certified on the course must complete it again; false leaves every earlier completion standing, for a typo or a broken link. An invalid package is rejected and its staged blob deleted. Requires scorm:write over the course's owner.

Parameters

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

Request body

application/jsonrequiredReplaceScormCoursePackageRequest
FieldTypeRequiredDescription
pathnamestringyes

matches ^scorm-courses\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/[^/]{1,100}$

file_namestringyes

1–255 characters

requires_recertificationbooleanyes

True when the new content must be completed again by everyone — new compliance material, say: completions of attempts on earlier package versions stop satisfying scorm_course_complete rules, an attempt still running an earlier version included. False for a minor fix — a typo, a broken link — that leaves every earlier completion standing. Attempts in progress keep running the version they started on either way.

Responses

StatusDescriptionBody
200The course, now serving the new version to fresh attempts.ScormCourse
400The request body failed validation, no upload exists at the pathname, or the package is not a runnable SCORM module.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller does not hold scorm:write over the course's owner.ErrorResponse
404No visible course has that id.ErrorResponse
409That uploaded package is already registered to a course.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
503File storage is not configured on this deployment.ErrorResponse
GET/api/scorm-courses/{course_id}/package-versions Bearer token

List a course's package versions

Lists every package the course has served, newest first: the registered upload as version 1, then one per replacement through PUT /scorm-courses/{course_id}/package. Each says what its manifest declared, whether it required recertification, and whether it is the version fresh attempts launch against; an attempt names its own version as package_version_number. Requires scorm:read over the course's owner.

Parameters

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

Responses

StatusDescriptionBody
200The course's package versions.ScormPackageVersionList
401The access token is missing or invalid.ErrorResponse
404No visible course has that id.ErrorResponse
500The database could not be read.ErrorResponse
GET/api/scorm-courses/{course_id}/permanent-deletion Bearer token

Preview permanently deleting a SCORM course

Counts everything DELETE on this path would remove: every learner's attempts (in-progress ones included), the learning records completions reported into, the proof rules requiring completion of the course, and the package. Nothing is changed. Requires scorm:delete over the course's owner — a grant separate from scorm:write, which only archives.

Parameters

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

Responses

StatusDescriptionBody
200What the deletion would take with it.DeletionImpact
401The access token is missing or invalid.ErrorResponse
403The caller does not hold scorm:delete over the course's owner.ErrorResponse
404No visible course has that id.ErrorResponse
500The database could not be read.ErrorResponse
DELETE/api/scorm-courses/{course_id}/permanent-deletion Bearer token

Permanently delete a SCORM course

Hard-deletes the course — unlike archiving, which only hides it from learners. Every attempt is deleted, the learning records completions reported into go with their score and pass/fail evidence (so whatever they counted toward certification requirements disappears), the scorm_course_complete rules pointing at the course are deleted too, and the package is removed from the file store. Irreversible. Preview the cost with GET first. Requires scorm:delete over the course's owner — a grant separate from scorm:write, which only archives.

Parameters

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

Responses

StatusDescriptionBody
204The course, its attempts, their records, its rules and the package are gone.—
401The access token is missing or invalid.ErrorResponse
403The caller does not hold scorm:delete over the course's owner.ErrorResponse
404No visible course has that id.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse
GET/api/scorm-courses/{course_id} Bearer token

Read one SCORM course

Reads one course. Requires scorm:read over the course's owner — its owning department when it has one, its organization otherwise.

Parameters

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

Responses

StatusDescriptionBody
200The course.ScormCourse
401The access token is missing or invalid.ErrorResponse
404No visible course has that id.ErrorResponse
500The database could not be read.ErrorResponse
PATCH/api/scorm-courses/{course_id} Bearer token

Edit or archive a course

Changes a course's name, description or audience (trainees, or trainers only), or archives/restores it. The package is replaced whole through PUT /scorm-courses/{course_id}/package, and the subject tags as a set through PUT /scorm-courses/{course_id}/subjects. Attempts are history, so there is no delete; archiving hides the course from learners. Requires scorm:write over the course's owner.

Parameters

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

Request body

application/jsonrequiredUpdateScormCourseRequest
FieldTypeRequiredDescription
namestringno

1–200 characters

descriptionstring | nullno

at most 5000 characters

audiencestringno

Whom the course is for. trainees: everyone its ownership admits — every member for an organization-owned course, the owning department's role holders for a department-owned one — trainers included. trainers: only holders of scorm:read over the course's owner, for modules that teach how to run the training rather than the training itself; the course is absent from everyone else's list and launches.

one of "trainees" | "trainers"

archivedbooleanno

True archives the course (hidden from learners); false restores it.

Responses

StatusDescriptionBody
200The updated course.ScormCourse
400The request body failed validation.ErrorResponse
401The access token is missing or invalid.ErrorResponse
403The caller does not hold scorm:write over the organization.ErrorResponse
404No visible course has that id.ErrorResponse
500The database could not be reached, or the write failed.ErrorResponse