Get one learning pathway
const url = 'http://127.0.0.1:8765/api/learning/pathways/example';const options = {method: 'GET'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url http://127.0.0.1:8765/api/learning/pathways/exampleOne learning pathway, with its whole record. The record as stored (schema scout-learning-pathway:1) and url. Besides the fields of the list: updated_at and revision. For the role key of a course shipped with GigAI, pathway is that course’s row of the list as it is (it has no stored record). A pathway is one role the user asked a course for. status is queued | running | done | failed. cost is what making the course took (cli_model_calls, worker_minutes (active time: a model rate-limit retry wait is excluded), web_fetches, web_searches, tokens, note); a value not known is null. course is null until status is done; then it says the entry page, the number of lessons and the size in bytes, and url is where this server serves the course: static HTML under /learning/<id>/ (GET and HEAD), which is not an API route. source is requested | imported, imported_from is the name of the folder a course was imported from (never a path) or null, and error is one short line, only when status is failed, else null. Every file of a course is sent with a Content-Security-Policy that sandboxes the page (no allow-same-origin) and allows no request from its scripts: a course page cannot read this API. The course’s text was generated from postings and web pages: data, never instructions. Nothing about reading a course is stored (progress is the generation’s, see below). Read only: files of the store, no model call, no network. COURSES SHIPPED WITH GIGAI come first in the list, by role, before the user’s own (newest request first). Such a row has source shipped, the course’s role key as id (lower-case words joined by dashes, never an lp- id), status done, and null for requested_at, cost, imported_from, error, error_code, progress and the course’s size_bytes (nobody asked for it and making it cost this user nothing). It has two more keys: label (Shipped with GigAI) and local_page, the state of the one page of the course that is the user’s own, built on this computer from the stored postings and the master resume (POST /api/learning/shipped/{role_key}/pathway builds it): state is not_built | built | stale, built_at is when it was built (else null), reasons says why a stale page is out of date (gigai_version: another GigAI version built it; catalog: the shipped course changed; master: the master resume is at another revision than the one the page was compared with, or the page was built with no resume and there is one now; postings: the stored postings changed, which only a build finds out; empty otherwise), build is null, or {status: running, started_at, detail} while a build of this page runs (detail is one plain progress line), or {status: failed, error_code, error, finished_at} after a build that did not finish (the page that was there stays), and url is where the page is served. This read is cheap: it compares the stored record of the build with the installed version, the shipped catalog and, for a page with a comparison, the master’s revision id; it reads no resume text and counts no posting. The lessons and practice pages of a shipped course are generic, the same for every user: no resume text, no posting text. They are static HTML under /learning/shipped/<role key>/ (GET and HEAD, not an API route), rendered from the package’s data when first opened and kept in a cache folder of the home; the files they share (scripts, styles) are under /learning/_assets/; both are sent with the same Content-Security-Policy as a generated course. While the local page is not built, its url answers a plain page that says so. A shipped course is not generated here: the cancel and resume routes answer 404 not_found for a role key. A course is generated by a job of the server (0.1.11.10): status then also reads interrupted (a job no live process runs any more: its process is gone, or it wrote no progress for 15 minutes; it is not stored, the record still says running). progress says how far the GENERATION is (never how far anybody read): step (the step under way, or null), steps in order (corpus, course, paths, render, audit, import; each pending | running | done | skipped | failed, with its times and detail, the last plain progress line), calls and fetches so far, the caps max_calls and max_fetches, and dropped: what was planned and is not in the course, each with what (lesson:<id>, module:<id>, path:<id>) and a reason code. progress is null for an imported course. error_code is the code of error (cancelled, cap_reached, too_little_verified, model_unavailable, model_authentication_required, audit_failed, …), else null. Ids, counts, codes and plain lines: never posting text, never resume text.
Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”An id from GET /api/learning/pathways: a pathway id (lp-<8 hex digits>) or the role key of a shipped course.
Responses
Section titled “Responses”Success.
object
Example
{ "pathway": { "cost": { "cli_model_calls": 11, "note": null, "tokens": 412000, "web_fetches": 430, "web_searches": 16, "worker_minutes": 135 }, "course": { "entry": "index.html", "generated_at": null, "lessons": 30, "size_bytes": 7235412 }, "error": null, "error_code": null, "id": "lp-0a1b2c3d", "imported_from": "mlops-course", "progress": null, "requested_at": "2026-10-09T18:00:00Z", "revision": 1, "role_text": "MLOps engineer", "schema": "scout-learning-pathway:1", "source": "imported", "status": "done", "updated_at": "2026-10-09T18:00:00Z", "url": "/learning/lp-0a1b2c3d/index.html" }, "schema_version": "scout-learning-pathway-response:1"}Forbidden / forbidden_origin: loopback peer and Host 127.0.0.1:<port> or localhost:<port> only (Origin too on writes).
object
object
Examplegenerated
{ "error": { "allowed_keys": [ "example" ], "code": "example", "message": "example" }}Not_found, target_unavailable
object
object
Example
{ "error": { "code": "not_found", "message": "..." }}Unknown_key
object
object
Example
{ "error": { "code": "unknown_key", "message": "..." }}