Create a lesson plan
API version 2026-10-affable-towhee
Starts generating a lesson plan and streams its progress. started names the plan as soon as it exists, so a dropped connection can reconnect with GET /v1/lesson-plans/{id}/stream. The stream ends with result or error. A plan served from the library arrives as a lone result.
Scopes lesson_plans:write
Parameters
Lingara-Versionheaderstringoptional- The API version to answer this request under. Without it, an access token gets the version its client is pinned to, and a request with no token gets the current version. The version still in development is reached only by naming it here. An unknown version answers
400with codeapi_version_unknown.GET /v1/versionslists the versions.
Request body application/json
contextstringrequiredsource_langstringrequiredtarget_langstringrequiredlevelintegerrequired
Responses
200 The plan's progress, then the plan
Stream events text/event-stream
Sends a keepalive comment every 15 seconds.
-
startedPlanStarted -
plan_idstringrequired
-
phasePlanPhase -
phasestringrequiredattemptintegerrequired
-
resultPlanResult Ends the stream -
planLessonPlanrequiredidstringrequiredstatusPlanStatusrequiredtitlestring | nulloptionalsource_langstringrequiredtarget_langstringrequiredlevelintegerrequiredcreated_atstringrequiredcompleted_atstring | nulloptionalai_generatedbooleanrequiredcontentLessonPlanContent | nulloptionalintroductionstring | nulloptionallearning_objectivesarray of stringrequiredvocabularyarray of PlanWordrequiredwordstringrequiredpronunciationstring | nulloptionaltranslationstringrequired
setsarray of PlanSetrequirednumberintegerrequiredcontextstring | nulloptionalquestionsarray of PlanQuestionrequiredtypestringrequiredpromptstringrequiredoptionsarray of string | nulloptionalanswerstringrequiredexplanationstringrequiredhintstring | nulloptional
-
errorStreamError Ends the stream -
Arrives inside the 200 response. The status line has already been sent, so a failure after the stream opens is reported as this event.
codestringrequiredmessagestringrequiredplan_idstring | nulloptional
Errors
402application/json- A metered client's call was refused before it spent anything.
spend_cap_reached: the client or its account has reached its monthly spending limit; raise the limit on the Integrations page.metered_billing_inactive: usage billing is not active for this account; set it up, or update the payment method, on the Integrations page. 410application/json- The API version this request is answered under has been discontinued. Send a supported version in
Lingara-Version, or re-pin the client. 4XXapplication/json- The request was refused.
codesays why, anderrorsays it in words. 503application/json · text/plain- The service is temporarily unavailable; retry after the number of seconds in
Retry-After. During maintenance the body is plain text rather than the error envelope. 5XXapplication/json- The request was refused.
codesays why, anderrorsays it in words.
codestringrequiredWhy the request was refused, as a stable code to branch on: for example
insufficient_scope(403),rate_limited(429) and, for a metered client,spend_cap_reached(402) andmetered_billing_inactive(402).errorstringrequired
Example
Prefer a library? See the Libraries section.
Example stream
event: started
data: {"plan_id":"3f1c2a9e-5b7d-4e21-9a0c-6d8e4f2b1a37"}
event: phase
data: {"phase":"selecting_vocabulary","attempt":1}
event: result
data: {"plan":{"id":"3f1c2a9e-5b7d-4e21-9a0c-6d8e4f2b1a37","status":"complete","title":"At the night market","source_lang":"en","target_lang":"zh","level":2,"created_at":"2026-09-23T10:00:00Z","completed_at":"2026-09-23T10:00:41Z","ai_generated":true,"content":{"introduction":"Order food and ask prices at a night market.","learning_objectives":["Ask how much something costs"],"vocabulary":[{"word":"多少钱","pronunciation":"duōshao qián","translation":"how much"}],"sets":[{"number":1,"questions":[{"type":"multiple_choice_word","prompt":"Which word asks for a price?","options":["多少钱","谢谢"],"answer":"多少钱","explanation":"多少钱 means how much money."}]}]}}}