Playground ↗ Postman ↗ Dashboard ↗
GET /v2/courses/{course_id}/progress

Course progress

Returns chapter-by-chapter status while a course is being built. Cheap to poll — designed for a 1–3s loop until progress_pct === 100.

If you’d rather not poll, register a webhook for course.completed and course.failed instead. See Register webhook.

Request

Headers

HeaderRequiredNotes
X-API-Keyyes
X-External-User-Idyes (or X-User-Id)Must own the course

Path parameters

course_id string (UUID) required
The course’s ID.

Returns

{
  "course_id": "8fa640c0-22e6-436b-becd-bf2cfc86741a",
  "course_status": "generating",
  "job_id": "j_01HW0XYZ…",
  "job_status": "running",
  "progress_pct": 60,
  "expected_chapters": 5,
  "completed_chapters": 3,
  "chapters": [
    { "order": 0, "title": "Sunlight & Chlorophyll", "status": "completed", "completed_at": "2026-05-19T14:02:51Z" },
    { "order": 1, "title": "The Calvin Cycle",       "status": "completed", "completed_at": "2026-05-19T14:03:12Z" },
    { "order": 2, "title": "Light-dependent rxns",   "status": "completed", "completed_at": "2026-05-19T14:03:30Z" },
    { "order": 3, "title": "C4 plants",              "status": "running",   "completed_at": null },
    { "order": 4, "title": "Field photosynthesis",   "status": "pending",   "completed_at": null }
  ],
  "error": null
}

If generation fails, course_status becomes "failed", job_status becomes "failed", and error carries the structured reason.

progress_pct is computed as completed_chapters / expected_chapters * 100, capped at 99 until the job itself reports completion. It hits 100 only when the entire course (including auto-generated study guide) is committed.

Errors

  • 404 — No course with that ID for the calling user.