Lingara Lingara المستندات أدلة التعلّم API المكتبات التطبيقات البناء تطبيق الويب
اللغة: العربية

إنشاء خطة درس

إصدار API 2026-10-affable-towhee

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

يبدأ إنشاء خطة درس ويبثّ تقدّمها. يحدّد started الخطة فور وجودها، بحيث يمكن للاتصال المنقطع أن يعيد الاتصال عبر GET /v1/lesson-plans/{id}/stream. ينتهي البث بـ result أو error. أما الخطة المقدَّمة من المكتبة فتصل على هيئة result منفرد.

النطاقات lesson_plans:write

المعاملات

Lingara-Versionheaderstringاختياري
إصدار API الذي يُجاب عن هذا الطلب به. بدونه، يحصل رمز الوصول على الإصدار الذي رُبط به عميله، ويحصل الطلب الذي لا رمز مميز فيه على الإصدار الحالي. لا يمكن الوصول إلى الإصدار الذي لا يزال قيد التطوير إلا بذكره هنا. الإصدار غير المعروف يُجاب عنه بـ 400 مع الرمز api_version_unknown. يسرد GET /v1/versions الإصدارات.

متن الطلب application/json

contextstringمطلوب
source_langstringمطلوب
target_langstringمطلوب
levelintegerمطلوب

الاستجابات

200 تقدّم الخطة، ثم الخطة

أحداث البث text/event-stream

يرسل تعليق إبقاء الاتصال (keepalive) كل 15 ثانية.

started PlanStarted
plan_idstringمطلوب
phase PlanPhase
phasestringمطلوب
attemptintegerمطلوب
result PlanResult ينهي البث
planLessonPlanمطلوب
idstringمطلوب
statusPlanStatusمطلوب
titlestring | nullاختياري
source_langstringمطلوب
target_langstringمطلوب
levelintegerمطلوب
created_atstringمطلوب
completed_atstring | nullاختياري
ai_generatedbooleanمطلوب
contentLessonPlanContent | nullاختياري
introductionstring | nullاختياري
learning_objectivesarray of stringمطلوب
vocabularyarray of PlanWordمطلوب
wordstringمطلوب
pronunciationstring | nullاختياري
translationstringمطلوب
setsarray of PlanSetمطلوب
numberintegerمطلوب
contextstring | nullاختياري
questionsarray of PlanQuestionمطلوب
typestringمطلوب
promptstringمطلوب
optionsarray of string | nullاختياري
answerstringمطلوب
explanationstringمطلوب
hintstring | nullاختياري
error StreamError ينهي البث

يصل داخل استجابة 200. سطر الحالة أُرسل بالفعل، لذا يُبلَّغ عن أي فشل بعد فتح البث على أنه هذا الحدث.

codestringمطلوب
messagestringمطلوب
plan_idstring | nullاختياري

الأخطاء

402application/json
رُفض استدعاء عميل يُفوتَر بحسب الاستهلاك قبل أن يُنفق أي شيء. spend_cap_reached: بلغ العميل أو حسابه حدّ الإنفاق الشهري؛ ارفع الحد في صفحة عمليات التكامل. metered_billing_inactive: الفوترة بحسب الاستهلاك غير مفعّلة لهذا الحساب؛ فعّلها أو حدّث طريقة الدفع في صفحة عمليات التكامل.
410application/json
تم إيقاف إصدار API الذي يُجاب عن هذا الطلب به. أرسل إصدارًا مدعومًا في Lingara-Version، أو اربط العميل بإصدار آخر.
4XXapplication/json
رُفض الطلب. يوضّح code السبب، ويشرحه error بالكلمات.
503application/json · text/plain
الخدمة غير متاحة مؤقتًا؛ أعد المحاولة بعد عدد الثواني المذكور في Retry-After. أثناء الصيانة يكون المتن نصًا عاديًا بدلًا من غلاف الخطأ.
5XXapplication/json
رُفض الطلب. يوضّح code السبب، ويشرحه error بالكلمات.
codestringمطلوب

سبب رفض الطلب، في صورة رمز ثابت يمكن التفرّع بناءً عليه: مثل insufficient_scope (403) وrate_limited (429)، ولعميل يُفوتَر بحسب الاستهلاك spend_cap_reached (402) وmetered_billing_inactive (402).

errorstringمطلوب

مثال

لغة مثال الشيفرة

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

تفضّل مكتبة؟ راجع قسم المكتبات.

مثال على البث

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

إذا اختلفت ترجمةٌ عن المرجع الإنجليزي، فالمرجع الإنجليزي هو الصحيح.