POST /v2/courses/generate
Generate a course from a topic
Creates a new course from a topic string. Use this when the learner has a subject in mind but no source material to upload.
Request
Headers
| Header | Required | Notes |
|---|---|---|
X-API-Key | yes | Your test or production key |
X-External-User-Id | yes (or X-User-Id) | Identifies the learner |
Content-Type | yes | application/json |
Body
topic string required The subject or question the course should teach. 3-500 characters. |
num_chapters integer default 4 Number of chapters to generate. |
search_enabled boolean default false Enriches chapter content with web search when the model supports it. |
learning_goal enum One of exams, career, curiosity, supplement. Overrides the user’s saved learning profile if set. |
Query parameters
mode enum default async async returns a job ID immediately; sync blocks until done; stream emits Server-Sent Events. |
Returns
A Course object with all chapters generated, plus a usage record. In async mode, returns a Job object — poll GET /jobs/{id}.
{
"status": "completed",
"mode": "sync",
"course": {
"id": "8fa640c0-22e6-436b-becd-bf2cfc86741a",
"title": "Photosynthesis: From Light to Life",
"chapters": [
{ "order_index": 0, "title": "Sunlight & Chlorophyll" },
{ "order_index": 1, "title": "The Calvin Cycle" }
]
}
}
For long generations (10+ chapters or file-based courses), use ?mode=async and either poll GET /jobs/{id} or register a webhook on course.completed and course.failed.
Errors
- 422 — Validation: missing
topic,num_chaptersout of 1-20 range, etc. - 403 —
TEST_USAGE_LIMITwhen your test key has burned through 5 courses this month. - 429 — Tenant or user rate limit. Backoff per
Retry-After. - 500 — Upstream LLM failure. Retry; include
X-Request-Idif you contact support.