Lingara Lingara Tài liệu Cẩm nang API Thư viện Ứng dụng Tạo Ứng dụng web
Ngôn ngữ: Tiếng Việt

Tạo giáo án

Phiên bản API 2026-10-affable-towhee

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

Bắt đầu tạo giáo án và truyền phát tiến trình. started cho biết định danh của giáo án ngay khi nó tồn tại, để kết nối bị ngắt có thể kết nối lại bằng GET /v1/lesson-plans/{id}/stream. Luồng kết thúc bằng result hoặc error. Giáo án lấy từ thư viện sẽ đến dưới dạng một result duy nhất.

Phạm vi lesson_plans:write

Tham số

Lingara-Versionheaderstringtùy chọn
Phiên bản API dùng để trả lời yêu cầu này. Nếu không có, token truy cập nhận phiên bản mà ứng dụng khách của nó được gắn, còn yêu cầu không có token nhận phiên bản hiện tại. Phiên bản đang phát triển chỉ có thể dùng bằng cách nêu tên nó ở đây. Phiên bản không xác định được trả lời bằng 400 với mã api_version_unknown. GET /v1/versions liệt kê các phiên bản.

Nội dung yêu cầu application/json

contextstringbắt buộc
source_langstringbắt buộc
target_langstringbắt buộc
levelintegerbắt buộc

Phản hồi

200 Tiến trình của giáo án, sau đó là giáo án

Sự kiện luồng text/event-stream

Gửi một chú thích keepalive mỗi 15 giây.

started PlanStarted
plan_idstringbắt buộc
phase PlanPhase
phasestringbắt buộc
attemptintegerbắt buộc
result PlanResult Kết thúc luồng
planLessonPlanbắt buộc
idstringbắt buộc
statusPlanStatusbắt buộc
titlestring | nulltùy chọn
source_langstringbắt buộc
target_langstringbắt buộc
levelintegerbắt buộc
created_atstringbắt buộc
completed_atstring | nulltùy chọn
ai_generatedbooleanbắt buộc
contentLessonPlanContent | nulltùy chọn
introductionstring | nulltùy chọn
learning_objectivesarray of stringbắt buộc
vocabularyarray of PlanWordbắt buộc
wordstringbắt buộc
pronunciationstring | nulltùy chọn
translationstringbắt buộc
setsarray of PlanSetbắt buộc
numberintegerbắt buộc
contextstring | nulltùy chọn
questionsarray of PlanQuestionbắt buộc
typestringbắt buộc
promptstringbắt buộc
optionsarray of string | nulltùy chọn
answerstringbắt buộc
explanationstringbắt buộc
hintstring | nulltùy chọn
error StreamError Kết thúc luồng

Đến bên trong phản hồi 200. Dòng trạng thái đã được gửi, nên lỗi xảy ra sau khi luồng mở được báo bằng sự kiện này.

codestringbắt buộc
messagestringbắt buộc
plan_idstring | nulltùy chọn

Lỗi

402application/json
Lệnh gọi của một ứng dụng khách tính phí theo mức dùng đã bị từ chối trước khi tiêu bất cứ thứ gì. spend_cap_reached: ứng dụng khách hoặc tài khoản của nó đã chạm hạn mức chi tiêu hằng tháng; hãy nâng hạn mức trên trang Tích hợp. metered_billing_inactive: tính phí theo mức dùng chưa được kích hoạt cho tài khoản này; hãy thiết lập hoặc cập nhật phương thức thanh toán trên trang Tích hợp.
410application/json
Phiên bản API dùng để trả lời yêu cầu này đã bị ngừng. Hãy gửi một phiên bản được hỗ trợ trong Lingara-Version, hoặc gắn ứng dụng khách với một phiên bản khác.
4XXapplication/json
Yêu cầu đã bị từ chối. code cho biết lý do, và error diễn đạt lý do đó bằng lời.
503application/json · text/plain
Dịch vụ tạm thời không khả dụng; hãy thử lại sau số giây ghi trong Retry-After. Trong thời gian bảo trì, phần thân là văn bản thuần thay vì phong bì lỗi.
5XXapplication/json
Yêu cầu đã bị từ chối. code cho biết lý do, và error diễn đạt lý do đó bằng lời.
codestringbắt buộc

Lý do yêu cầu bị từ chối, dưới dạng một mã ổn định để rẽ nhánh: ví dụ insufficient_scope (403), rate_limited (429) và, với ứng dụng khách tính phí theo mức dùng, spend_cap_reached (402) và metered_billing_inactive (402).

errorstringbắt buộc

Ví dụ

Ngôn ngữ của mã mẫu

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

Muốn dùng thư viện? Xem mục Thư viện.

Luồng ví dụ

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

Nếu bản dịch và tài liệu tham chiếu tiếng Anh khác nhau, tài liệu tham chiếu tiếng Anh là bản đúng.