welearninsync API
ดึงข้อมูลวิชา คาบ รายชื่อ และผลคะแนนของสถาบันไปใช้ในระบบทะเบียน Moodle หรือ dashboard — อ่านอย่างเดียว
สเปก OpenAPI 3.1 (JSON)การยืนยันตัวตน
ผู้ดูแลสถาบันสร้าง API key ที่ "จัดการสถาบัน → เชื่อมต่อระบบอื่น" แล้วส่งใน header ทุก request key หนึ่งอันเห็นเฉพาะข้อมูลของสถาบันนั้น และเฉพาะสิทธิ์ที่เลือกไว้
curl https://<your-domain>/api/v1/courses \ -H "Authorization: Bearer lsk_live_…"
เฉลยของคำถามไม่ออกทาง API ไม่ว่า key จะมีสิทธิ์อะไร
Endpoints
| Path | สิทธิ์ | ได้อะไร |
|---|---|---|
| GET /api/v1/courses | sessions:read | วิชาทั้งหมดของสถาบัน |
| GET /api/v1/courses/{courseId}/sessions | sessions:read | คาบเรียนของวิชา |
| GET /api/v1/courses/{courseId}/roster | roster:read | รายชื่อนักศึกษาของวิชา |
| GET /api/v1/courses/{courseId}/gradebook | results:read | การเข้าเรียน การมีส่วนร่วม คะแนน ทั้งวิชา |
| GET /api/v1/sessions/{sessionId}/results | results:read | ผลของคาบเดียว รายคนและรายข้อ |
ข้อตกลง
- หน้าข้อมูลแบบ cursor: ส่ง ?limit= (1–200) และ ?after=<next_cursor> ไปขอหน้าถัดไป
- อัตราส่วนเป็นทศนิยม 0–1 (ไม่ใช่เปอร์เซ็นต์) หรือ null ถ้ายังไม่มีตัวหาร
- จำกัด 120 request ต่อนาทีต่อ key — เกินได้ 429 พร้อม Retry-After
- error รูปแบบเดียวกันทุก endpoint พร้อม request_id — แจ้ง request_id เมื่อติดต่อ support
{
"error": {
"type": "insufficient_scope",
"message": "missing scope roster:read",
"request_id": "0b6f…"
}
}Webhooks
ให้ welearninsync แจ้งระบบของคุณทันทีที่เกิดเหตุการณ์ เช่น จบคาบแล้วดึงผลคะแนนต่อได้เลย — payload มีแค่ชนิด event กับ id ไม่มีข้อมูลนักศึกษา ให้ปลายทางเรียก API ด้วย key ของตัวเองเพื่อดึงข้อมูล
Event
session.started— session_id, course_idsession.ended— session_id, course_idround.opened— session_id, question_id, round_id, seqround.closed— session_id, question_id, round_id, seqroster.updated— course_id
POST /your-endpoint
X-LearnSync-Event: session.ended
X-LearnSync-Delivery: 7d1c…
X-LearnSync-Signature: t=1790000000,v1=5f2a…
{"data": {"course_id": "…", "session_id": "…"}, "event": "session.ended", "created_at": "2026-10-01T09:30:00+00:00"}ตรวจลายเซ็น
ทุก request มี header X-LearnSync-Signature: t=<เวลา>,v1=<HMAC-SHA256> คำนวณจาก "<t>.<body ดิบ>" ด้วย signing secret ของ webhook นั้น — ตรวจกับ body ดิบก่อน parse JSON และปฏิเสธถ้า t เก่ากว่า 5 นาที (กัน replay)
import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody: the exact bytes received — verify BEFORE JSON.parse
export function verify(secret, signatureHeader, rawBody) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(signatureHeader ?? "");
if (!m) return false;
if (Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false; // replay
const expected = createHmac("sha256", secret).update(`${m[1]}.${rawBody}`).digest();
return timingSafeEqual(expected, Buffer.from(m[2], "hex"));
}ตอบ 2xx ภายใน 10 วินาที = สำเร็จ อย่างอื่นส่งใหม่หลัง 1 นาที, 5 นาที, 30 นาที, 2 ชม., 6 ชม. แล้วเลิก — ปลายทางที่ไม่ตอบติดกันถูกพักอัตโนมัติ กดส่งซ้ำได้จากหน้าจัดการ
event อาจมาไม่ตรงลำดับ และอาจมาซ้ำ — ใช้ X-LearnSync-Delivery กันประมวลผลซ้ำ และ created_at ใน payload เพื่อเรียงลำดับ