Tài liệu API
Thao tác ghi dữ liệu đi qua các Route Handler trong src/app/api. Trang đọc dữ liệu trực tiếp bằng Prisma trong Server Component, nên không có API công khai để đọc danh mục khóa học. Các API nhận và trả JSON, xác thực bằng cookie phiên và tự kiểm tra quyền.
Xác thực
Đăng nhập và phiên do Auth.js xử lý.
/api/auth/[...nextauth]Đăng nhập, đăng xuất và đọc phiên (Auth.js)
/api/auth/change-passwordĐổi mật khẩu (bắt buộc ở lần đăng nhập đầu)
/api/auth/registerTự đăng ký; trả 404 khi ALLOW_SELF_REGISTER khác true
/api/auth/session-expiredXóa cookie của phiên không còn hợp lệ (ví dụ tài khoản bị khóa) rồi chuyển về trang đăng nhập
Ví dụ: GET /api/auth/session
{
"user": {
"id": "clx...",
"name": "...",
"email": "learner@lms.rivasoft.vn",
"role": "LEARNER",
"mustChangePassword": false
},
"expires": "2026-10-26T00:00:00.000Z"
}Khoa, khóa học và lớp học
Quản lý đào tạo (Quản lý đào tạo trở lên)Quản lý đào tạo+
/api/admin/departmentsXem danh sách, tạo khoa
/api/admin/departments/[id]Sửa, xóa khoa
/api/admin/coursesTạo khóa học
/api/admin/courses/[id]Xem, sửa khóa học
/api/admin/courses/[id]/teachersPhân công giảng viên, đổi vai trò giảng viên trong khóa
/api/admin/courses/[id]/teachers/[userId]Gỡ giảng viên khỏi khóa học
/api/admin/classesTạo lớp học
/api/admin/classes/[id]Xem, sửa lớp học
/api/admin/classes/[id]/statusĐổi trạng thái lớp học
/api/admin/classes/[id]/transferChuyển lớp cho giảng viên phụ trách khác
/api/admin/classes/[id]/enrollmentsGhi danh học viên vào lớp theo danh sách email hoặc tệp CSV
/api/admin/classes/[id]/enrollments/[enrollmentId]/cancelHủy ghi danh của một học viên
/api/admin/classes/[id]/enrollments/[enrollmentId]/transferChuyển học viên sang lớp khác của cùng khóa học
/api/admin/usersTạo tài khoản (trả về mật khẩu tạm)
/api/admin/users/[id]/roleĐổi vai trò
/api/admin/users/[id]/statusKhóa hoặc mở khóa tài khoản
/api/admin/users/[id]/reset-passwordĐặt lại mật khẩu
/api/admin/settings/site-nameĐổi tên hệ thống (chỉ Quản trị hệ thống)
/api/cron/chat-retentionJob định kỳ: xóa lịch sử trò chuyện AI cũ hơn CHAT_RETENTION_DAYS ngày (mặc định 180). Gọi kèm header Authorization: Bearer <CRON_SECRET>
Soạn nội dung (giảng viên được phân công, Quản lý đào tạo trở lên)Giảng viên+
/api/trainer/courses/[courseId]/lessonsXem danh sách, tạo bài học
/api/trainer/courses/[courseId]/lessons/orderSắp xếp thứ tự bài học
/api/trainer/courses/[courseId]/lessons/[lessonId]Xem, sửa, xóa bài học
/api/trainer/courses/[courseId]/lessons/[lessonId]/materialsThêm tài liệu
/api/trainer/courses/[courseId]/lessons/[lessonId]/materials/[materialId]Sửa, xóa tài liệu
/api/trainer/courses/[courseId]/lessons/[lessonId]/materials/from-libraryĐưa một học liệu từ kho học liệu khóa học vào bài học (bản trong bài học tự cập nhật khi học liệu gốc được sửa)
/api/trainer/courses/[courseId]/libraryXem, thêm học liệu khóa học (video YouTube/Vimeo/MP4, PDF, hình ảnh, liên kết, văn bản) dùng chung cho mọi lớp
/api/trainer/courses/[courseId]/library/[itemId]Sửa (đồng bộ sang các bài học đang dùng), xóa học liệu khóa học
/api/trainer/courses/[courseId]/lessons/[lessonId]/materials/[materialId]/video-settingsXem, lưu cài đặt video: xem tiếp, vị trí bắt đầu, ngưỡng hoàn thành (0–1), chế độ câu hỏi
/api/trainer/courses/[courseId]/lessons/[lessonId]/materials/[materialId]/quizzesXem danh sách mốc câu hỏi trong video (kèm đáp án), tạo mốc kèm câu hỏi Một lựa chọn / Nhiều lựa chọn / Đúng-Sai
/api/trainer/courses/[courseId]/lessons/[lessonId]/materials/[materialId]/quizzes/[quizId]Sửa, xóa mốc câu hỏi; sửa câu hỏi, đáp án hoặc điểm khi đã có lần làm bài thì tăng phiên bản
/api/trainer/courses/[courseId]/lessons/[lessonId]/assignmentsXem danh sách, tạo bài tập của bài học
/api/trainer/courses/[courseId]/lessons/[lessonId]/assignments/[assignmentId]Sửa, xóa bài tập (không xóa được khi đã có bài nộp)
/api/trainer/courses/[courseId]/lessons/[lessonId]/assignments/[assignmentId]/classes/[classId]Đặt hạn nộp riêng cho một lớp
/api/trainer/gradingHàng chờ chấm của giảng viên, lọc theo lớp, bài tập và trạng thái
/api/trainer/grading/[submissionId]Xem bài nộp và lịch sử chấm; chấm điểm theo tiêu chí hoặc trả bài
Ghi danh và học tập
Dành cho mọi người đã đăng nhập.
/api/enrollmentsGhi danh vào lớp học (lớp đang mở, cho phép tự ghi danh và còn chỗ)
/api/enrollmentsDanh sách ghi danh của bạn
/api/lessons/completeĐánh dấu hoàn thành bài học
/api/assignments/submitNộp bài tập
/api/assignments/[assignmentId]/submissionNộp bài hoặc nộp lại (chỉ nộp lại khi bài bị trả về)
/api/uploadsTải file lên (multipart: file, kind)
/api/files/[...key]Tải file về; quyền đọc tùy loại file
/api/ai/chatGửi tin nhắn cho trợ lý AI
/api/ai/chat/streamGửi tin nhắn cho trợ lý AI, câu trả lời trả về dần (NDJSON)
/api/ai/quotaSố lượt hỏi AI còn lại hôm nay
/api/learning/quizzes/[quizId]/attemptsBắt đầu hoặc tiếp tục lần làm bài của một mốc câu hỏi trong video (body: enrollmentId). Trả câu hỏi không kèm đáp án đúng; 409 khi hết lượt làm
/api/learning/quiz-attempts/[attemptId]/submitNộp lần làm bài và chấm trên server. Header Idempotency-Key (không bắt buộc): gửi lại trả đúng kết quả cũ. Trả điểm (0–1), đạt hay chưa, trạng thái hoàn thành bài học
/api/learning/materials/[materialId]/quiz-statusTrạng thái các mốc câu hỏi của một video theo ghi danh (enrollmentId), không kèm câu hỏi
/api/learning/materials/[materialId]/videoVideo tương tác của học viên (?enrollmentId=): cấu hình, vị trí xem tiếp, tỷ lệ đã xem và các mốc câu hỏi kèm trạng thái (không kèm câu hỏi, đáp án)
/api/learning/materials/[materialId]/progressGhi nhận thời gian đã xem (heartbeat mỗi 15 giây, nhận cả sendBeacon): { enrollmentId, segments, positionSec, rate, durationSec, clientSeq }; tự hoàn thành bài học khi đủ điều kiện
Ví dụ: POST /api/enrollments
// Yêu cầu
{ "classId": "clx..." }
// Phản hồi
{
"success": true,
"enrollmentId": "clx...",
"status": "PENDING",
"courseSlug": "...",
"message": "Đã gửi đăng ký. Đơn của bạn đang chờ duyệt."
}Phản hồi lỗi
Mọi API trả lỗi cùng một dạng: message là thông báo tiếng Việt hiển thị được cho người dùng, code là mã lỗi để code xử lý.
// 401
{ "message": "Vui lòng đăng nhập để tiếp tục", "code": "UNAUTHORIZED" }
// 403
{ "message": "Bạn không có quyền thực hiện thao tác này", "code": "FORBIDDEN" }
// 403 (POST /api/enrollments)
{ "message": "Lớp học này không cho phép tự ghi danh. Vui lòng liên hệ quản lý đào tạo.", "code": "SELF_ENROLL_CLOSED" }
// 404
{ "message": "Không tìm thấy dữ liệu", "code": "NOT_FOUND" }