Giao diện
API Gateway
Gốc: https://api.chuyenchon.com (cục bộ: http://127.0.0.1:8788).
Quy ước chung
Phản hồi thành công luôn bọc trong data:
json
{ "data": { "…": "…" } }Danh sách có thêm thông tin phân trang:
json
{ "data": { "items": [], "total": 18, "page": 1, "per_page": 24 } }Lỗi:
json
{ "error": { "code": 404, "message": "Không tìm thấy trường \"abc\"." } }Tham số phân trang: page (mặc định 1) và per_page (mặc định 24, trần 100).
Endpoint
GET /health
Kiểm tra Worker và kết nối D1. Trả về số trường đang có.
GET /v1/meta
Từ điển cho bộ lọc: danh sách tỉnh thành, môn học và thống kê tổng. Cache 1 giờ ở biên.
GET /v1/schools
| Tham số | Ý nghĩa |
|---|---|
province | slug tỉnh thành |
subject | slug môn chuyên |
type | chuyen, nang-khieu, chat-luong-cao, thuong |
q | khớp gần đúng theo tên và tên gọi khác |
GET /v1/schools/:slug
Hồ sơ đầy đủ: môn chuyên, toàn bộ đợt tuyển sinh, tối đa 50 đề thi gần nhất, giáo viên và 20 hoạt động gần nhất — tất cả trong một lượt db.batch().
GET /v1/schools/compare/list?slugs=a,b,c
So sánh tối đa 4 trường, giữ nguyên thứ tự slug người dùng truyền vào.
| Tham số | Ý nghĩa |
|---|---|
slugs | Danh sách slug, phân tách bằng dấu phẩy |
grade | Khối lớp tuyển sinh (6 hoặc 10) — nếu bỏ trống sẽ trộn lẫn các khối |
year | Năm tuyển sinh |
Mỗi trường trả về kèm fees (học phí các năm) và admissions, trong đó mỗi đợt tuyển sinh có đủ subjects, rounds, timeline, documents.
GET /v1/admissions
Lọc theo school, province, year, grade.
GET /v1/admissions/:schoolSlug
Toàn bộ lộ trình tuyển sinh của một trường, gom theo năm, kèm fees (học phí). Mỗi phương thức tuyển sinh trả về đầy đủ bốn nhóm dữ liệu con:
json
{
"school": { "slug": "…", "name": "…" },
"fees": [{ "year": 2025, "tuition_monthly": 4000000, "months_per_year": 9, "is_estimate": 1 }],
"years": [{
"year": 2025,
"routes": [{
"route_name": "Sơ tuyển kết hợp đánh giá năng lực",
"places": 105, "classes": 3, "application_fee": 500000,
"subjects": [{ "name": "Bài đánh giá năng lực tổng hợp", "role": "nang-luc",
"duration_minutes": 120, "max_score": 100, "weight": 1 }],
"rounds": [{ "name": "Vòng 1: Sơ tuyển", "kind": "so-tuyen", "scoring": "…" }],
"timeline": [{ "starts_on": "2025-05-06", "ends_on": "2025-05-26", "title": "Phát hành hồ sơ" }],
"documents": [{ "title": "Học bạ cấp tiểu học (bản công chứng)", "required": 1 }]
}]
}]
}Các bản ghi con được nạp bằng một lượt db.batch() cho toàn bộ đợt tuyển sinh của trường, không truy vấn lặp theo từng đợt.
GET /v1/exams
Lọc theo school, subject, year, grade, type, difficulty.
GET /v1/exams/facets
Số lượng đề theo năm và theo loại — dùng dựng bộ lọc mà không phải tải hết danh sách.
GET /v1/exams/:slug
Chi tiết đề, kèm tối đa 8 đề liên quan (ưu tiên cùng trường, sau đó cùng môn).
GET /v1/competitions
Lọc theo subject, level, format, grade, và upcoming=1 để chỉ lấy kỳ thi còn hạn đăng ký hoặc chưa diễn ra.
GET /v1/competitions/calendar
Kỳ thi gom theo tháng, từ from (mặc định hôm nay).
GET /v1/competitions/:slug
Chi tiết kèm danh sách trường tham dự và thành tích.
GET /v1/teachers · GET /v1/teachers/:slug
Lọc theo school, subject, q.
GET /v1/search?q=
Tìm kiếm hợp nhất trên mọi thực thể. Trả về cả items (đã xếp hạng) lẫn groups (gom theo entity_type) để giao diện dựng được kết quả nhiều lát cắt trong một lần gọi. Thêm type= để giới hạn một loại.
GET /v1/search/suggest?q=
Tối đa 8 gợi ý cho ô tìm kiếm ở header.
POST /v1/admin/reindex
Dựng lại toàn bộ chỉ mục tìm kiếm từ dữ liệu gốc. Cần header:
Authorization: Bearer <ADMIN_TOKEN>Trả về { "data": { "indexed": 359 } }. Chạy sau mỗi lần nạp hoặc sửa dữ liệu hàng loạt.
Ví dụ
bash
curl 'https://api.chuyenchon.com/v1/schools?province=ha-noi&subject=tin-hoc'
curl 'https://api.chuyenchon.com/v1/search?q=chuyen%20su%20pham'
curl -X POST https://api.chuyenchon.com/v1/admin/reindex \
-H "Authorization: Bearer $ADMIN_TOKEN"