Lingara Lingara Dokumentasi Panduan API Pustaka Aplikasi Buat Aplikasi web
Bahasa: Bahasa Indonesia

Buat rencana pelajaran

Versi API 2026-10-affable-towhee

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

Mulai membuat rencana pelajaran dan mengalirkan progresnya. started menyebut rencana segera setelah ada, sehingga koneksi yang terputus dapat tersambung kembali dengan GET /v1/lesson-plans/{id}/stream. Stream berakhir dengan result atau error. Rencana yang diambil dari pustaka datang sebagai satu result saja.

Cakupan lesson_plans:write

Parameter

Lingara-Versionheaderstringopsional
Versi API yang digunakan untuk menjawab permintaan ini. Tanpanya, token akses mendapatkan versi yang disematkan pada kliennya, dan permintaan tanpa token mendapatkan versi saat ini. Versi yang masih dalam pengembangan hanya dapat dicapai dengan menyebutkannya di sini. Versi yang tidak dikenal dijawab 400 dengan kode api_version_unknown. GET /v1/versions mencantumkan versi-versinya.

Isi permintaan application/json

contextstringwajib
source_langstringwajib
target_langstringwajib
levelintegerwajib

Respons

200 Progres rencana, lalu rencananya

Peristiwa stream text/event-stream

Mengirim komentar keepalive setiap 15 detik.

started PlanStarted
plan_idstringwajib
phase PlanPhase
phasestringwajib
attemptintegerwajib
result PlanResult Mengakhiri stream
planLessonPlanwajib
idstringwajib
statusPlanStatuswajib
titlestring | nullopsional
source_langstringwajib
target_langstringwajib
levelintegerwajib
created_atstringwajib
completed_atstring | nullopsional
ai_generatedbooleanwajib
contentLessonPlanContent | nullopsional
introductionstring | nullopsional
learning_objectivesarray of stringwajib
vocabularyarray of PlanWordwajib
wordstringwajib
pronunciationstring | nullopsional
translationstringwajib
setsarray of PlanSetwajib
numberintegerwajib
contextstring | nullopsional
questionsarray of PlanQuestionwajib
typestringwajib
promptstringwajib
optionsarray of string | nullopsional
answerstringwajib
explanationstringwajib
hintstring | nullopsional
error StreamError Mengakhiri stream

Tiba di dalam respons 200. Baris status sudah dikirim, sehingga kegagalan setelah stream dibuka dilaporkan sebagai event ini.

codestringwajib
messagestringwajib
plan_idstring | nullopsional

Galat

402application/json
Panggilan klien dengan penagihan per pemakaian ditolak sebelum menghabiskan apa pun. spend_cap_reached: klien atau akunnya telah mencapai batas pengeluaran bulanannya; naikkan batasnya di halaman Integrasi. metered_billing_inactive: penagihan per pemakaian tidak aktif untuk akun ini; siapkan, atau perbarui metode pembayarannya, di halaman Integrasi.
410application/json
Versi API yang digunakan untuk menjawab permintaan ini telah dihentikan. Kirim versi yang didukung di Lingara-Version, atau sematkan klien ke versi lain.
4XXapplication/json
Permintaan ditolak. code menyebutkan alasannya, dan error menjelaskannya dengan kata-kata.
503application/json · text/plain
Layanan sementara tidak tersedia; coba lagi setelah jumlah detik di Retry-After. Selama pemeliharaan, isi respons berupa teks biasa, bukan amplop galat.
5XXapplication/json
Permintaan ditolak. code menyebutkan alasannya, dan error menjelaskannya dengan kata-kata.
codestringwajib

Alasan permintaan ditolak, sebagai kode tetap untuk percabangan: misalnya insufficient_scope (403), rate_limited (429) dan, untuk klien dengan penagihan per pemakaian, spend_cap_reached (402) dan metered_billing_inactive (402).

errorstringwajib

Contoh

Bahasa contoh kode

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";
    }
}

Lebih suka pustaka? Lihat bagian Pustaka.

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

Jika terjemahan berbeda dengan referensi berbahasa Inggris, referensi berbahasa Inggris yang berlaku.