chapter_id.
All endpoints are authenticated — they run behind auth:sanctum, the “user is not blocked” check, and the per-company policy middleware. Always send your Sanctum token as a Bearer header.
Table of contents
- Base URL & Headers
- Chapter quizzes in the payload
- List chapters
- Reorder chapters
- Create a chapter
- Retrieve a chapter
- Update a chapter
- Permanently delete a chapter
- Postman setup
Base URL & Headers
Y-m-d H:i:s format. Boolean query params accept true, false, 1, 0.
Chapterpositionis 1-based and unique per training. A new chapter is not auto-positioned — you must send thepositionyou want.
Chapter quizzes in the payload
Since 19/10/2026 a chapter can hold any number of quizzes (before, adding a second quiz turned the first one into an exam). Every chapter object returned byGET /chapters and GET /chapter/{id} therefore carries two keys:
Who sees what:
- Students only get the published chapter quizzes (
is_published = 1), in both keys. - Staff (instructor, content manager, admin, super admin) also get the drafts, so editors can list them. Check each quiz’s
is_published.
Quiz row: training_id is null for a chapter quiz (it is found through chapter_id), it carries its slug, its instructor and the computed rating / sales fields. The same two keys appear in the chapters of GET /training/{id}, the login payload (GET /auth/user) and the chapter exports.
⚠️ LikeGET /training/{id}, these endpoints return each quiz’s options with theiris_correctflags andexplanationtexts. Use them for the course player of an owned training and for the editors, never for the marketplace.
List chapters
GET /chapters
Returns a paginated list of chapters for a given training. Each chapter always includes its quizzes (plus the deprecated quiz, see Chapter quizzes in the payload), each with its question tree (questions → options → option items). Lessons are included only when you ask for them.
Query parameters
Example request
Example response — 200 OK
Called by an instructor: chapter 40 has a published quiz and a draft, chapter 41 has no lessons but still returns its quiz. A student would not see quiz 78 (draft).
"quizzes": [] and "quiz": null.
Reorder chapters
POST /chapters/reorder
Bulk-updates the position of multiple chapters in a single call. The request body is a bare array — not an object.
Body
An array of{ id, position } pairs.
Example request
Response — 200 OK
Create a chapter
POST /chapter
Body parameters
Example request
Response — 200 OK
Retrieve a chapter
GET /chapter/{id}
Returns a single chapter with all its quizzes (quizzes, creation order) and their question trees (questions → options → option items), plus the deprecated quiz (= the first one). Students only get the published quizzes; staff also get the drafts — see Chapter quizzes in the payload. Lessons are not included in this endpoint — use GET /lessons?chapter_id={id} to list them.
Before 19/10/2026 this endpoint returned the chapter’s singlequizwhatever its publish state, so a student could receive a draft quiz here whileGET /training/{id}(published only) did not show it.
Example request
Response — 200 OK
Called by a student: the draft quiz 78 of chapter 40 is not listed.
Unknown id — 500
The controller catches the “not found” exception in its generic handler, so an unknown id answers 500 (not 404) with the model message:
Update a chapter
POST /chapter/{id}
Updates an existing chapter. The chapter must belong to the training_id supplied in the body — otherwise 404 is returned.
Body parameters
Example request
Response — 200 OK
Permanently delete a chapter
DELETE /chapter/{id}/hard_delete
Force-deletes the chapter and all its lessons. This is irreversible. The quizzes.chapter_id foreign key cascades on delete, so every quiz of the chapter is removed by the database too (there can be several since 19/10/2026), together with their questions and the students’ attempts on them (those foreign keys cascade as well).
⚠️ This endpoint does not soft-delete — both the chapter and every lesson it contains are removed from the database immediately. If you need a recoverable operation, archive upstream (e.g. the training) instead.
Example request
Response — 200 OK
Postman setup
- Environment variables.
base_url— your API root, e.g.http://localhost:8000token— the Sanctum token returned byPOST /auth/login
- Collection-level headers.
Accept: application/jsonAuthorization: Bearer {{token}}
- Request bodies.
- JSON bodies → Body → raw → JSON
- For Reorder, remember the body is a bare JSON array, not an object wrapped in a key.
- Smoke-test flow.
POST /chapter— createGET /chapters?training_id={id}— verify it appearsPOST /chapter/{id}— updatePOST /chapters/reorder— reorder with peersGET /chapter/{id}— confirmDELETE /chapter/{id}/hard_delete— cleanup