1. Mục tiêu
Tài liệu này hướng dẫn đơn vị tích hợp giao diện lập trình ứng dụng PartnerApi để đồng bộ dữ liệu thời khóa biểu.
Tài liệu tập trung vào:
- Cách gọi bằng
curl - Ý nghĩa và ràng buộc của toàn bộ dữ liệu đầu vào
- Cách đọc dữ liệu phản hồi theo từng bản ghi
2. Thông tin kết nối
2.1. Địa chỉ dịch vụ
- Địa chỉ gọi dịch vụ:
https://lmsbpartnerapi.vstudy.edu.vn/ - Tài liệu kiểm tra nhanh:
https://lmsbpartnerapi.vstudy.edu.vn/swagger/index.html
2.2. Header bắt buộc
Tất cả giao diện lập trình ứng dụng đồng bộ yêu cầu:
X-Api-Key: <api-key-do-don-vi-duoc-cap>Content-Type: application/json
PartnerId được lấy từ X-Api-Key (không truyền trong dữ liệu thân yêu cầu).
Để lấy X-Api-Key, vui lòng liên hệ đơn vị QIG.
3. Danh sách endpoint thời khóa biểu
POST /api/lms-base/time-tables: Tạo mới hoặc cập nhật danh sách thời khóa biểuDELETE /api/lms-base/time-tables: Xóa danh sách thời khóa biểu theoSourceId
4. Tạo mới hoặc cập nhật thời khóa biểu
4.1. cURL tạo mới hoặc cập nhật
curl --location --request POST "https://lmsbpartnerapi.vstudy.edu.vn/api/lms-base/time-tables" \
--header "X-Api-Key: <YOUR_API_KEY>" \
--header "Content-Type: application/json" \
--data-raw '[
{
"sourceId": "TT-20260411-0001",
"sourceTeachingPlanId": "TP-20260411-0001",
"doetCode": "01",
"divisionCode": "00004",
"schoolCode": "01000865",
"academicYearCode": 2025,
"gradeLevelCode": "04",
"semesterCode": "2",
"classCode": "4A08",
"weekNumber": 15,
"dayOfWeek": 2,
"session": "SANG",
"period": 1,
"startTime": "2026-04-06T00:00:00Z",
"endTime": "2026-04-06T00:45:00Z",
"subjectCode": "0201",
"teacherPinCode": "001056008234",
"note": "Dong bo thoi khoa bieu",
"teachingType": "B"
}
]'4.2. Ý nghĩa toàn bộ dữ liệu đầu vào (UpsertTimeTableRequest)
| Trường | Kiểu | Bắt buộc | Ý nghĩa | Ràng buộc chính |
|---|---|---|---|---|
| sourceId | string | Có | Mã bản ghi từ hệ thống nguồn | Không rỗng, dùng chung với PartnerId để định danh tạo mới hoặc cập nhật |
| sourceTeachingPlanId | string? | Không | Mã lịch báo giảng liên kết từ hệ thống nguồn | Chuỗi tự do, dùng để đối chiếu nội bộ nếu cần |
| doetCode | string | Có | Mã Sở Giáo dục và Đào tạo | Không rỗng, phải tồn tại trong danh mục Sở Giáo dục và Đào tạo |
| divisionCode | string? | Không | Mã phòng hoặc xã hoặc phường | Nếu có giá trị thì phải tồn tại theo doetCode + academicYearCode |
| schoolCode | string | Có | Mã trường | Không rỗng, phải thuộc doetCode và thuộc divisionCode nếu có, trong đúng academicYearCode |
| branchCode | string? | Không | Mã phân hiệu (cơ sở) của lớp | Bắt buộc khi classCode trùng giữa nhiều phân hiệu của cùng schoolCode; lớp thuộc cơ sở chính thì gửi bằng schoolCode. Xem mục 4.3 |
| academicYearCode | int | Có | Năm học | Phải lớn hơn 0 |
| gradeLevelCode | string | Có | Mã khối hoặc cấp học | Chỉ nhận: 01: Mầm non, 02: Tiểu học, 03: THCS, 04: THPT, 05:GDTX |
| semesterCode | string | Có | Học kỳ | Chỉ nhận: 1 hoặc 2 |
| classCode | string | Có | Mã lớp | Không rỗng, phải tồn tại trong schoolCode + academicYearCode, và thuộc branchCode nếu có gửi |
| weekNumber | int | Có | Tuần học | Phải lớn hơn 0 |
| dayOfWeek | byte | Có | Thứ trong tuần | Chỉ nhận từ 2 đến 8 |
| session | string | Có | Buổi học | Chỉ nhận SANG hoặc CHIEU |
| period | int | Có | Số tiết | Phải lớn hơn 0 |
| startTime | DateTime | Có | Giờ bắt đầu tiết học | Định dạng ISO 8601 theo múi giờ UTC |
| endTime | DateTime? | Không | Giờ kết thúc tiết học | Định dạng ISO 8601 theo múi giờ UTC |
| subjectCode | string | Có | Mã môn học | Không rỗng, phải tồn tại và đang hoạt động trong danh mục môn học |
| teacherPinCode | string | Có | Căn cước công dân của giáo viên | Tồn tại trong cơ sở dữ liệu và thuộc trường schoolCode |
| note | string? | Không | Ghi chú | Chuỗi tự do |
| teachingType | string? | Không | Kiểu giảng dạy | Chỉ nhận: B, LT, TH, OT, KT, TB, THI, LEN_LOP, DAY_BU, DAY_THAY, LAP_GIO, NGHI_LE, NGHI_DAY; mặc định B nếu không gửi |
Ghi chú:
- Ý nghĩa các giá trị của
teachingType: B: Bài mới, giảng dạy kiến thức mới.LT: Luyện tập, củng cố kiến thức thông qua bài tập.TH: Thực hành hoặc thí nghiệm, vận dụng lý thuyết vào thực tiễn.OT: Ôn tập, hệ thống lại kiến thức sau một chương hoặc chuyên đề.KT: Kiểm tra, các bài kiểm tra thường xuyên hoặc định kỳ.TB: Trả bài, chữa bài kiểm tra cho học sinh.THI: Thi, tham gia kỳ thi.LEN_LOP: Lên lớp.DAY_BU: Dạy bù.DAY_THAY: Dạy thay.LAP_GIO: Lấp giờ.NGHI_LE: Nghỉ lễ.NGHI_DAY: Nghỉ dạy.- Hệ thống tự lấy
TeacherName,SubjectNametừ dữ liệu tham chiếu. - Hệ thống tạo mới hoặc cập nhật theo
PartnerId + sourceId. - Thời khóa biểu có khóa nghiệp vụ duy nhất:
SchoolCode + AcademicYearCode + BranchCode + SemesterCode + ClassCode + WeekNumber + DayOfWeek + Session + Period. Hai lớp trùngclassCodeở hai phân hiệu khác nhau có thể có tiết học cùng thời điểm. - Nếu trùng khóa nghiệp vụ với bản ghi khác thì hệ thống trả lỗi xung đột cho bản ghi đó.
4.3. Đồng bộ lớp thuộc phân hiệu (branchCode)
Một trường có thể có cơ sở chính và nhiều phân hiệu, các phân hiệu dùng chung schoolCode và có thể có lớp trùng classCode. Trường branchCode giúp hệ thống xác định đúng lớp:
- Nếu
classCodelà duy nhất trongschoolCode + academicYearCode: có thể bỏ trốngbranchCode, hệ thống tự xác định phân hiệu theo lớp. - Nếu
classCodetrùng giữa nhiều phân hiệu: bắt buộc gửibranchCode, nếu không bản ghi bị từ chối. - Lớp thuộc cơ sở chính: gửi
branchCodebằng chínhschoolCode. - Lớp thuộc phân hiệu: gửi
branchCodebằng mã phân hiệu trong danh mục trường của Cơ sở dữ liệu ngành. branchCodekhông phân biệt chữ hoa, chữ thường; nếu không khớp với phân hiệu của lớp thì bản ghi bị từ chối.- Hệ thống lưu mã phân hiệu theo lớp đã xác định được, dùng để phân quyền xem dữ liệu theo phân hiệu.
Ví dụ phần tử gửi cho lớp thuộc phân hiệu:
{
"sourceId": "TT-20260411-0002",
"doetCode": "01",
"schoolCode": "01000865",
"branchCode": "<MA_PHAN_HIEU>",
"classCode": "4A08",
"...": "các trường khác như ví dụ ở mục 4.1"
}4.4. Mô hình dữ liệu phản hồi khi tạo mới hoặc cập nhật
Mô hình phản hồi cấp ngoài:
{
"data": [
{
"id": "string-ulid-hoac-null",
"sourceId": "string",
"isCreated": true,
"isSuccess": true,
"message": "string-hoac-null",
"processedAt": "2026-04-08T07:30:00.0000000Z"
}
],
"message": "string",
"success": true
}Mô hình chi tiết từng phần tử trong data (TimeTableSyncResponse):
id: định danh kiểuUlid, có thểnullkhi bản ghi lỗisourceId: mã bản ghi từ hệ thống nguồnisCreated:true: tạo mớifalse: cập nhậtnull: bản ghi lỗiisSuccess: kết quả xử lý từng bản ghimessage: thông điệp chi tiết từng bản ghiprocessedAt: thời điểm xử lý theo múi giờ UTC
Ví dụ phản hồi:
{
"data": [
{
"id": "01KNXQVNZZ1111BCX9CY49W999",
"sourceId": "TT-20260411-0001",
"isCreated": true,
"isSuccess": true,
"message": "Đồng bộ thành công.",
"processedAt": "2026-04-11T07:45:13.2944263Z"
}
],
"message": "Đồng bộ 1 thời khóa biểu: thành công 1, lỗi 0.",
"success": true
}5. Xóa thời khóa biểu
5.1. cURL xóa
curl --location --request DELETE "https://lmsbpartnerapi.vstudy.edu.vn/api/lms-base/time-tables" \
--header "X-Api-Key: <YOUR_API_KEY>" \
--header "Content-Type: application/json" \
--data-raw '[
"TT-20260411-0001",
"TT-20260411-0002"
]'Dữ liệu đầu vào của giao diện lập trình ứng dụng xóa:
- Dữ liệu thân yêu cầu là mảng
string[] - Mỗi phần tử là
SourceIdcần xóa - Hệ thống xóa theo khóa
PartnerId + SourceId
5.2. Mô hình dữ liệu phản hồi khi xóa
Mô hình phản hồi cấp ngoài:
{
"data": [
{
"sourceId": "string",
"deleted": true,
"processedAt": "2026-04-08T07:30:00.0000000Z"
}
],
"message": "string",
"success": true
}Mô hình chi tiết từng phần tử trong data (TimeTableDeleteResponse):
sourceId: mã bản ghi từ hệ thống nguồndeleted:true: đã xóafalse: không tìm thấy để xóaprocessedAt: thời điểm xử lý theo múi giờ UTC
Ví dụ phản hồi:
{
"data": [
{
"sourceId": "TT-20260411-0001",
"deleted": true,
"processedAt": "2026-04-11T07:47:30.1200000Z"
}
],
"message": "Xử lý xóa 1 thời khóa biểu, xóa thành công 1 bản ghi.",
"success": true
}6. Mã trạng thái thường gặp
200 OK: yêu cầu được xử lý (có thể có bản ghi thành công và bản ghi lỗi trong cùng dữ liệu phản hồi)400 Bad Request: dữ liệu thân yêu cầu không hợp lệ ở mức yêu cầu (ví dụ danh sách rỗng)401 Unauthorized: thiếu hoặc saiX-Api-Key409 Conflict: xung đột dữ liệu (thường do trùng khóa nghiệp vụ)
Ví dụ thông điệp lỗi theo từng bản ghi:
Bản ghi thời khóa biểu tại vị trí 3 không hợp lệ: SemesterCode chỉ chấp nhận giá trị 1 hoặc 2.Bản ghi tại vị trí 5 không hợp lệ: SubjectCode '9999' không tồn tại hoặc không hoạt động.Bản ghi tại vị trí 2 không hợp lệ: ClassCode '4A08' thuộc nhiều phân hiệu; cần gửi BranchCode.Bản ghi tại vị trí 4 không hợp lệ: ClassCode '4A08' không tồn tại trong SchoolCode/BranchCode/Năm học tương ứng.
7. Khuyến nghị tích hợp
- Luôn giữ
sourceIdổn định cho cùng một bản ghi nghiệp vụ để bảo đảm cập nhật đúng bản ghi. - Chuẩn hóa dữ liệu mã trước khi gửi (cắt khoảng trắng ở đầu và cuối).
- Gửi thời gian theo múi giờ UTC, định dạng ISO 8601 (
yyyy-MM-ddTHH:mm:ssZ). - Đồng bộ theo lô vừa phải (ví dụ 100 đến 500 bản ghi mỗi lần) để dễ theo dõi lỗi.
- Luôn đọc
data[].isSuccessvàdata[].messageđể xử lý gửi lại theo từng bản ghi lỗi. - Với trường có phân hiệu, nên luôn gửi
branchCodecho mọi bản ghi để tránh lỗi khi phát sinh lớp trùng mã giữa các phân hiệu. - Bản ghi đã đồng bộ trước khi có
branchCodenên được gửi lại để hệ thống cập nhật mã phân hiệu.
8. Lịch sử cập nhật
2026-09-27: Bổ sung trườngbranchCode(mã phân hiệu) cho dữ liệu đầu vào, khóa nghiệp vụ và thông điệp lỗi liên quan.
