Lingara Lingara Documentación Guías API Bibliotecas Apps Crear Aplicación web
Idioma: Español

Crear un plan de lección

Versión de la API 2026-10-affable-towhee

post https://api.getlingara.com/v1/lesson-plans

Empieza a generar un plan de lección y transmite su progreso. started identifica el plan en cuanto existe, de modo que una conexión interrumpida pueda reconectarse con GET /v1/lesson-plans/{id}/stream. El flujo termina con result o error. Un plan servido desde la biblioteca llega como un único result.

Ámbitos lesson_plans:write

Parámetros

Lingara-Versionheaderstringopcional
La versión de la API con la que se responde a esta solicitud. Sin ella, un token de acceso recibe la versión a la que está vinculado su cliente, y una solicitud sin token recibe la versión actual. La versión aún en desarrollo solo se alcanza nombrándola aquí. Una versión desconocida responde 400 con el código api_version_unknown. GET /v1/versions enumera las versiones.

Cuerpo de la solicitud application/json

contextstringobligatorio
source_langstringobligatorio
target_langstringobligatorio
levelintegerobligatorio

Respuestas

200 El progreso del plan y luego el plan

Eventos del flujo text/event-stream

Envía un comentario keepalive cada 15 segundos.

started PlanStarted
plan_idstringobligatorio
phase PlanPhase
phasestringobligatorio
attemptintegerobligatorio
result PlanResult Termina el flujo
planLessonPlanobligatorio
idstringobligatorio
statusPlanStatusobligatorio
titlestring | nullopcional
source_langstringobligatorio
target_langstringobligatorio
levelintegerobligatorio
created_atstringobligatorio
completed_atstring | nullopcional
ai_generatedbooleanobligatorio
contentLessonPlanContent | nullopcional
introductionstring | nullopcional
learning_objectivesarray of stringobligatorio
vocabularyarray of PlanWordobligatorio
wordstringobligatorio
pronunciationstring | nullopcional
translationstringobligatorio
setsarray of PlanSetobligatorio
numberintegerobligatorio
contextstring | nullopcional
questionsarray of PlanQuestionobligatorio
typestringobligatorio
promptstringobligatorio
optionsarray of string | nullopcional
answerstringobligatorio
explanationstringobligatorio
hintstring | nullopcional
error StreamError Termina el flujo

Llega dentro de la respuesta 200. La línea de estado ya se ha enviado, así que un fallo después de abrirse el flujo se notifica como este evento.

codestringobligatorio
messagestringobligatorio
plan_idstring | nullopcional

Errores

402application/json
Se rechazó la llamada de un cliente con facturación por uso antes de que gastara nada. spend_cap_reached: el cliente o su cuenta ha alcanzado su límite de gasto mensual; sube el límite en la página Integraciones. metered_billing_inactive: la facturación por uso no está activa para esta cuenta; configúrala o actualiza el método de pago en la página Integraciones.
410application/json
La versión de la API con la que se responde a esta solicitud se ha retirado. Envía una versión admitida en Lingara-Version o vincula el cliente a otra versión.
4XXapplication/json
La solicitud fue rechazada. code indica el motivo y error lo explica con palabras.
503application/json · text/plain
El servicio no está disponible temporalmente; vuelve a intentarlo tras el número de segundos indicado en Retry-After. Durante el mantenimiento, el cuerpo es texto sin formato en lugar del sobre de error.
5XXapplication/json
La solicitud fue rechazada. code indica el motivo y error lo explica con palabras.
codestringobligatorio

Por qué se rechazó la solicitud, como un código estable con el que ramificar: por ejemplo insufficient_scope (403), rate_limited (429) y, para un cliente con facturación por uso, spend_cap_reached (402) y metered_billing_inactive (402).

errorstringobligatorio

Ejemplo

Lenguaje del ejemplo de código

curl

curl -N -X POST "https://api.getlingara.com/v1/lesson-plans" \
  -H "Authorization: Bearer $LINGARA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"context":"Ordering food at a night market","source_lang":"en","target_lang":"zh","level":2}'

TypeScript

const stream = client.createLessonPlan({
  context: "ordering at a night market",
  source_lang: "en",
  target_lang: "zh",
  level: 2,
});
for await (const ev of stream) {
  if (ev.event === "started") console.log("plan", ev.data.plan_id);
  if (ev.event === "phase") console.log("working:", ev.data.phase);
  if (ev.event === "result") console.log(ev.data.plan.title);
}

Rust

use lingara::models::{CreateLessonPlanEvent, LessonPlanCreateRequest};

let request = LessonPlanCreateRequest {
    context: "ordering at a night market".into(),
    source_lang: "en".into(),
    target_lang: "zh".into(),
    level: 2,
};
let mut stream = client.create_lesson_plan(&request).await?;
while let Some(event) = stream.next().await {
    match event? {
        CreateLessonPlanEvent::Started(started) => println!("plan {}", started.plan_id),
        CreateLessonPlanEvent::Phase(phase) => println!("working: {}", phase.phase),
        CreateLessonPlanEvent::Result(result) => println!("{}", result.plan.title.unwrap_or_default()),
        _ => {}
    }
}

Go

s, err := client.CreateLessonPlan(ctx, lingara.LessonPlanCreateRequest{
	Context:    "ordering at a night market",
	SourceLang: "en",
	TargetLang: "zh",
	Level:      2,
})
if err != nil {
	return err
}
defer s.Close()
for ev, err := range s.Events() {
	if err != nil {
		return err
	}
	switch e := ev.(type) {
	case lingara.CreateLessonPlanEventStarted:
		fmt.Println("plan", e.Data.PlanID)
	case lingara.CreateLessonPlanEventPhase:
		fmt.Println("working:", e.Data.Phase)
	case lingara.CreateLessonPlanEventResult:
		if e.Data.Plan.Title != nil {
			fmt.Println(*e.Data.Plan.Title)
		}
	}
}

Java

import com.getlingara.client.model.CreateLessonPlanEvent;
import com.getlingara.client.model.LessonPlanCreateRequest;

LessonPlanCreateRequest request =
    new LessonPlanCreateRequest()
        .context("Ordering at a night market")
        .level(2)
        .sourceLang("en")
        .targetLang("zh");
try (EventStream<CreateLessonPlanEvent> stream = client.createLessonPlan(request)) {
  for (CreateLessonPlanEvent event : stream) {
    if (event instanceof CreateLessonPlanEvent.Started started) {
      // Keep the id: streamLessonPlan rejoins a generation that was cut off.
      System.out.println("plan " + started.data().getPlanId());
    } else if (event instanceof CreateLessonPlanEvent.Phase phase) {
      System.out.println("phase " + phase.data().getPhase());
    } else if (event instanceof CreateLessonPlanEvent.Result result) {
      System.out.println(result.data().getPlan().getTitle());
    }
  }
}

Kotlin

import com.getlingara.kotlin.LingaraClient
import com.getlingara.kotlin.model.CreateLessonPlanEvent
import com.getlingara.kotlin.model.LessonPlanCreateRequest

val request =
    LessonPlanCreateRequest(context = "Ordering at a night market", sourceLang = "en", targetLang = "zh", level = 2)
client.createLessonPlan(request).use { stream ->
    stream.collect { event ->
        when (event) {
            // Keep the id: streamLessonPlan rejoins a generation that was cut off.
            is CreateLessonPlanEvent.Started -> println("plan ${event.data.planId}")
            is CreateLessonPlanEvent.Phase -> println("phase ${event.data.phase}")
            is CreateLessonPlanEvent.Result -> println(event.data.plan.title)
        }
    }
}

Ruby

client.create_lesson_plan(context: "ordering at a night market", source_lang: "en", target_lang: "zh", level: 2) do |event|
  case event
  in Lingara::CreateLessonPlanEventStarted => started then puts "plan #{started.data.plan_id}"
  in Lingara::CreateLessonPlanEventPhase => phase then puts "working: #{phase.data.phase}"
  in Lingara::CreateLessonPlanEventResult => result then puts "ready: #{result.data.plan.title}"
  else nil
  end
end

PHP

use Lingara\Model\LessonPlanCreateRequest;
use Lingara\Stream\CreateLessonPlanEvent;

$request = new LessonPlanCreateRequest([
    'context' => 'ordering at a night market',
    'source_lang' => 'en',
    'target_lang' => 'zh',
    'level' => 2,
]);
foreach ($client->createLessonPlan($request) as $event) {
    if ($event instanceof CreateLessonPlanEvent\Started) {
        echo 'plan ', $event->data->getPlanId(), "\n";
    } elseif ($event instanceof CreateLessonPlanEvent\Phase) {
        echo 'phase: ', $event->data->getPhase(), "\n";
    } elseif ($event instanceof CreateLessonPlanEvent\Result) {
        echo 'ready: ', $event->data->getPlan()->getTitle(), "\n";
    }
}

¿Prefieres una biblioteca? Consulta la sección Bibliotecas.

Ejemplo de flujo

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."}]}]}}}

Si una traducción y la referencia en inglés difieren, prevalece la referencia en inglés.