Skip to content

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
provinceslug tỉnh thành
subjectslug môn chuyên
typechuyen, nang-khieu, chat-luong-cao, thuong
qkhớ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
slugsDanh sách slug, phân tách bằng dấu phẩy
gradeKhối lớp tuyển sinh (6 hoặc 10) — nếu bỏ trống sẽ trộn lẫn các khối
yearNă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"

Tài liệu nội bộ dự án Chuyên Chọn.