School grade calculator (TT 22) API
Subject averages, semester and year ratings Tốt / Khá / Đạt / Chưa đạt, promotion, re-tests and awards for grades 6–12 under Thông tư 22/2021/TT-BGDĐT.
Applies the assessment rules of Thông tư 22/2021/TT-BGDĐT (lower and upper secondary, grades 6–12): the semester average of each scored subject (ΣĐĐGtx + 2 × mid-term + 3 × final) / (number of regular scores + 5), the year average (semester I + 2 × semester II) / 3, rounded to one decimal, and Đạt / Chưa đạt for comment-assessed subjects. Send the component scores or the averages you already have.
The learning result of each semester and of the year is rated Tốt, Khá, Đạt or Chưa đạt with the thresholds of Điều 9 (6.5 / 8.0 for at least six subjects, 5.0 / 6.5, 3.5…), including the rule that raises a result lowered by two or more levels because of a single subject. With the conduct rating and absences, the API decides promotion, summer conduct training or re-tests (and lists the subjects to re-test) and the Học sinh Giỏi / Xuất sắc awards. The number of regular scores is checked against the periods per year.
Formulas and thresholds are unchanged by TT 89/2026/TT-BGDĐT (from 1/12/2026), which changes test organisation and re-test timing. Primary school (TT 27/2020) is not covered.
Parameters
| Name | In | Type | Required | Default | |
|---|---|---|---|---|---|
subjects | body | array | yes | Subjects: {name, type: "score" | "comment", periods?, hk1, hk2}; a semester is an average (8.5 / "Đ") or {regular: [...], mid, final}. | |
conduct | body | string | no | Year conduct rating: Tốt, Khá, Đạt, Chưa đạt (for promotion and awards). | |
absences | body | number | no | Days of absence in the year (more than 45: repeat the year). |
Example
curl -X POST "https://apibox.io.vn/v1/vn-school-grade" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"subjects":[{"name":"Toán","periods":140,"hk1":{"regular":[8,9,7,8],"mid":8,"final":9},"hk2":9.1},{"name":"Ngữ văn","hk1":7.5,"hk2":8.2},{"name":"Tiếng Anh","hk1":9,"hk2":9.1},{"name":"GDCD","hk1":8.5,"hk2":9},{"name":"KHTN","hk1":8,"hk2":8.4},{"name":"Lịch sử và Địa lý","hk1":7.8,"hk2":8.6},{"name":"Thể dục","type":"comment","hk1":"Đ","hk2":"Đ"}],"conduct":"Tốt","absences":2}'const res = await fetch('https://apibox.io.vn/v1/vn-school-grade', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"subjects": [
{
"name": "Toán",
"periods": 140,
"hk1": {
"regular": [
8,
9,
7,
8
],
"mid": 8,
"final": 9
},
"hk2": 9.1
},
{
"name": "Ngữ văn",
"hk1": 7.5,
"hk2": 8.2
},
{
"name": "Tiếng Anh",
"hk1": 9,
"hk2": 9.1
},
{
"name": "GDCD",
"hk1": 8.5,
"hk2": 9
},
{
"name": "KHTN",
"hk1": 8,
"hk2": 8.4
},
{
"name": "Lịch sử và Địa lý",
"hk1": 7.8,
"hk2": 8.6
},
{
"name": "Thể dục",
"type": "comment",
"hk1": "Đ",
"hk2": "Đ"
}
],
"conduct": "Tốt",
"absences": 2
}),
});
const data = await res.json();
console.log(data);import requests
res = requests.post(
"https://apibox.io.vn/v1/vn-school-grade",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"subjects": [{"name": "Toán", "periods": 140, "hk1": {"regular": [8, 9, 7, 8], "mid": 8, "final": 9}, "hk2": 9.1}, {"name": "Ngữ văn", "hk1": 7.5, "hk2": 8.2}, {"name": "Tiếng Anh", "hk1": 9, "hk2": 9.1}, {"name": "GDCD", "hk1": 8.5, "hk2": 9}, {"name": "KHTN", "hk1": 8, "hk2": 8.4}, {"name": "Lịch sử và Địa lý", "hk1": 7.8, "hk2": 8.6}, {"name": "Thể dục", "type": "comment", "hk1": "Đ", "hk2": "Đ"}], "conduct": "Tốt", "absences": 2},
timeout=30,
)
print(res.json())<?php
$ch = curl_init('https://apibox.io.vn/v1/vn-school-grade');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"subjects":[{"name":"Toán","periods":140,"hk1":{"regular":[8,9,7,8],"mid":8,"final":9},"hk2":9.1},{"name":"Ngữ văn","hk1":7.5,"hk2":8.2},{"name":"Tiếng Anh","hk1":9,"hk2":9.1},{"name":"GDCD","hk1":8.5,"hk2":9},{"name":"KHTN","hk1":8,"hk2":8.4},{"name":"Lịch sử và Địa lý","hk1":7.8,"hk2":8.6},{"name":"Thể dục","type":"comment","hk1":"Đ","hk2":"Đ"}],"conduct":"Tốt","absences":2}',
]);
$response = curl_exec($ch);
print_r(json_decode($response, true));Response
{
"subjects": [
{
"name": "Toán",
"type": "score",
"hk1": 8.3,
"hk2": 9.1,
"year": 8.8,
"details": {
"hk1": {
"regular": [
8,
9,
7,
8
],
"mid": 8,
"final": 9,
"formula": "(8 + 9 + 7 + 8 + 2×8 + 3×9) / 9"
},
"hk2": {
"given_average": 9.1
}
}
},
{
"name": "Ngữ văn",
"type": "score",
"hk1": 7.5,
"hk2": 8.2,
"year": 8,
"details": {
"hk1": {
"given_average": 7.5
},
"hk2": {
"given_average": 8.2
}
}
},
{
"name": "Thể dục",
"type": "comment",
"hk1": "Đạt",
"hk2": "Đạt",
"year": "Đạt",
"details": {
"hk1": {
"given": "Đ"
},
"hk2": {
"given": "Đ"
}
}
}
],
"learning": {
"hk1": {
"rating": "Khá",
"rating_en": "Good",
"level": 2
},
"hk2": {
"rating": "Tốt",
"rating_en": "Very good",
"level": 3
},
"year": {
"rating": "Tốt",
"rating_en": "Very good",
"level": 3
}
},
"conduct": "Tốt",
"promotion": {
"decision": "promoted",
"decision_vi": "Được lên lớp"
},
"award": {
"title": "Học sinh Giỏi",
"title_en": "Good student",
"note": "Xuất sắc needs ≥ 6 subjects with a year average ≥ 9.0 (has 1)"
},
"legal": {
"circular": "Thông tư 22/2021/TT-BGDĐT, sửa đổi bởi TT 10/2025/TT-BGDĐT và TT 89/2026/TT-BGDĐT",
"scope": "Lower and upper secondary (grades 6–12); primary school uses TT 27/2020/TT-BGDĐT"
},
"reviewed": "2026-11-11"
}
Use cases
- Compute averages in an electronic report-book app
- Let parents check their child’s rating before the school report
- Validate grade entry in school management software
- Simulate the scores needed for a Giỏi award
FAQ
How many regular scores per subject?
Per semester: 2 for subjects with 35 periods a year, 3 for 36–70, 4 above 70; comment subjects have 2. A warning shows when the count differs.
Is there still an overall average of all subjects?
No. TT 22 rates the learning result from the subject averages only; the API does not compute a global average.
What does adjusted_from mean?
The result was lowered by two or more levels by one subject only, so it was raised one level as Điều 9 requires.
Related APIs
JSON Validator
Check JSON syntax with exact line and column of errors, and validate data against a JSON Schema (draft 4, 7, 2019-09 or 2020-12).
{ }JSON Formatter
Pretty print JSON with 0-8 spaces or tabs, minify it, or sort object keys recursively. Syntax errors are reported with line and column.
CSVCSV to JSON
Convert CSV into an array of JSON objects using the header row, with delimiter auto-detection, number and boolean typing, and row-level errors.