Tính công chấm công API
Chuyển dữ liệu máy chấm công thành bảng công: giờ làm và số công mỗi ngày, phút đi muộn / về sớm, thiếu chấm, tăng ca theo loại ngày, giờ làm đêm.
Gửi dữ liệu chấm công xuất từ máy (ZKTeco, Ronald Jack, Wise Eye… dạng CSV hoặc JSON) cùng các ca làm việc. Cột dữ liệu được nhận theo tiêu đề thường gặp (AC-No., Mã NV, Name, Họ tên, Time, Thời gian, Ngày + Giờ, nhiều giờ chấm trong một ô) hoặc khai báo bằng columns; ngày đọc theo dd/mm/yyyy trừ khi đặt date_format=mdy / ymd. Ca có giờ vào, giờ ra (ca đêm qua ngày hôm sau vẫn được), giờ nghỉ giữa ca và số phút cho phép đi muộn, về sớm.
Mỗi nhân viên mỗi ngày được gán ca có giờ vào gần lần chấm đầu nhất, lấy giờ vào đầu và giờ ra cuối, tính phút đi muộn, về sớm, số phút làm (trừ giờ nghỉ) và số công, đánh dấu thiếu chấm, giờ tăng ca sau ca (từ ot_min_minutes, có thể làm tròn) và số phút làm đêm từ 22:00 đến 06:00 (Bộ luật Lao động 2019, Điều 106). Ngày nghỉ hằng tuần (rest_days, mặc định Chủ nhật) và ngày lễ (tính từ /v1/vn-holidays, hoặc danh sách holidays riêng) thì toàn bộ thời gian làm là tăng ca loại đó.
Bảng tổng hợp mỗi nhân viên gồm số ngày và số công, số giờ, số lần đi muộn / về sớm, ngày thiếu chấm, ngày vắng, giờ tăng ca chia theo ngày thường / ngày nghỉ / ngày lễ (trả ít nhất 150% / 200% / 300%, Điều 98) và tăng ca ban đêm, kèm cảnh báo khi tăng ca quá 40 giờ trong tháng (Điều 107). API không áp đơn giá, nên kết quả dùng được cho mọi cách tính lương.
Tham số
| Tên | Vị trí | Kiểu | Bắt buộc | Mặc định | |
|---|---|---|---|---|---|
csv | body | string | không | Dữ liệu chấm công dạng CSV / TSV (hoặc mảng JSON logs, hoặc file CSV). | |
logs | body | array | không | Các dòng như [{"employee":"1","time":"2026-11-02 07:58"}]. | |
columns | body | object | không | Khai báo cột: employee, name, datetime hoặc date + time. | |
shifts | body | array | không | Các ca [{"code","start","end","break_start","break_end","grace_late","grace_early"}] (mặc định 08:00-17:00, nghỉ 12-13). | |
from | body | string | không | Đầu kỳ (YYYY-MM-DD) để tính ngày vắng và công chuẩn. | |
to | body | string | không | Cuối kỳ (YYYY-MM-DD). | |
rest_days | body | string | không | 0 | Ngày nghỉ hằng tuần, 0 = Chủ nhật … 6 = Thứ Bảy, ví dụ 6,0. |
holidays | body | array | không | Danh sách ngày lễ riêng (mặc định: lễ Tết Việt Nam), hoặc none. | |
ot_min_minutes | body | number | không | 30 | Số phút tăng ca tối thiểu được tính sau ca. |
ot_round_minutes | body | number | không | 0 | Làm tròn xuống giờ tăng ca theo bước này (ví dụ 15). |
date_format | body | string | không | dmy | dmy, mdy hoặc ymd cho ngày có dấu gạch chéo. |
Ví dụ
curl -X POST "https://apibox.io.vn/v1/vn-timesheet" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"csv":"AC-No.,Name,Time\n1,Nguyễn An,02/11/2026 07:58\n1,Nguyễn An,02/11/2026 17:45\n1,Nguyễn An,03/11/2026 08:12\n1,Nguyễn An,03/11/2026 16:50\n1,Nguyễn An,08/11/2026 08:00\n1,Nguyễn An,08/11/2026 12:00","from":"2026-11-02","to":"2026-11-08"}'const res = await fetch('https://apibox.io.vn/v1/vn-timesheet', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"csv": "AC-No.,Name,Time\n1,Nguyễn An,02/11/2026 07:58\n1,Nguyễn An,02/11/2026 17:45\n1,Nguyễn An,03/11/2026 08:12\n1,Nguyễn An,03/11/2026 16:50\n1,Nguyễn An,08/11/2026 08:00\n1,Nguyễn An,08/11/2026 12:00",
"from": "2026-11-02",
"to": "2026-11-08"
}),
});
const data = await res.json();
console.log(data);import requests
res = requests.post(
"https://apibox.io.vn/v1/vn-timesheet",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"csv": "AC-No.,Name,Time\n1,Nguyễn An,02/11/2026 07:58\n1,Nguyễn An,02/11/2026 17:45\n1,Nguyễn An,03/11/2026 08:12\n1,Nguyễn An,03/11/2026 16:50\n1,Nguyễn An,08/11/2026 08:00\n1,Nguyễn An,08/11/2026 12:00", "from": "2026-11-02", "to": "2026-11-08"},
timeout=30,
)
print(res.json())<?php
$ch = curl_init('https://apibox.io.vn/v1/vn-timesheet');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"csv":"AC-No.,Name,Time\\n1,Nguyễn An,02/11/2026 07:58\\n1,Nguyễn An,02/11/2026 17:45\\n1,Nguyễn An,03/11/2026 08:12\\n1,Nguyễn An,03/11/2026 16:50\\n1,Nguyễn An,08/11/2026 08:00\\n1,Nguyễn An,08/11/2026 12:00","from":"2026-11-02","to":"2026-11-08"}',
]);
$response = curl_exec($ch);
print_r(json_decode($response, true));Kết quả trả về
{
"period": {
"from": "2026-11-02",
"to": "2026-11-08",
"standard_workdays": 6,
"rest_days": [
0
],
"holidays": [],
"holidays_source": "vn-holidays (Labour Code Điều 112; official schedules where announced)"
},
"shifts": [
{
"code": "HC",
"start": "08:00",
"end": "17:00",
"break": "12:00-13:00",
"minutes": 480,
"grace_late": 0,
"grace_early": 0,
"overnight": false
}
],
"rules": {
"ot_min_minutes": 30,
"ot_round_minutes": 0,
"count_early_ot": false,
"ot_window_hours": 8,
"dedupe_minutes": 2,
"night": "22:00-06:00"
},
"punches": 6,
"employee_count": 1,
"employees": [
{
"employee": "1",
"name": "Nguyễn An",
"work_days": 2,
"work_units": 1.95,
"worked_hours": 15.63,
"late_count": 1,
"late_minutes": 12,
"early_count": 1,
"early_minutes": 10,
"missing_punch_days": 0,
"absent_days": 4,
"absent_dates": [
"2026-11-04",
"2026-11-05",
"2026-11-06",
"2026-11-07"
],
"ot_hours": {
"workday": 0.75,
"rest_day": 4,
"holiday": 0,
"total": 4.75
},
"night_hours": 0,
"ot_night_hours": 0,
"ot_limit_warnings": []
}
],
"days": [
{
"employee": "1",
"name": "Nguyễn An",
"date": "2026-11-03",
"weekday_vi": "Thứ Ba",
"day_type": "workday",
"shift": "HC",
"shift_time": "08:00-17:00",
"punches": [
"2026-11-03 08:12",
"2026-11-03 16:50"
],
"first_in": "2026-11-03 08:12",
"last_out": "2026-11-03 16:50",
"status": "late_and_early",
"late_minutes": 12,
"early_minutes": 10,
"worked_minutes": 458,
"work_units": 0.95,
"ot_minutes": 0,
"ot_type": null,
"night_minutes": 0,
"ot_night_minutes": 0
},
{
"employee": "1",
"name": "Nguyễn An",
"date": "2026-11-08",
"weekday_vi": "Chủ nhật",
"day_type": "rest_day",
"shift": "HC",
"shift_time": "08:00-17:00",
"punches": [
"2026-11-08 08:00",
"2026-11-08 12:00"
],
"first_in": "2026-11-08 08:00",
"last_out": "2026-11-08 12:00",
"status": "overtime_day",
"late_minutes": 0,
"early_minutes": 0,
"worked_minutes": 0,
"work_units": 0,
"ot_minutes": 240,
"ot_type": "rest_day",
"night_minutes": 0,
"ot_night_minutes": 0
},
{
"…": "…"
}
],
"days_truncated": false,
"legal_basis": "Bộ luật Lao động 2019: Điều 106 (night work 22:00-06:00), Điều 98 (OT pay 150% / 200% / 300%, night +30%, night OT +20%), Điều 107 (OT max 40 h/month, 200 h/year), Điều 112 (holidays); NĐ 145/2020/NĐ-CP",
"reviewed": "2026-11-11"
}
Ứng dụng
- Tính công tháng cho phần mềm lương doanh nghiệp nhỏ từ file máy chấm công
- Thống kê đi muộn, về sớm trên dashboard nhân sự
- Tách giờ tăng ca theo mức hưởng trước khi tính lương
- Kiểm tra giờ tăng ca so với giới hạn 40 giờ mỗi tháng
Hỏi đáp
Hỗ trợ máy chấm công nào?
Mọi file xuất có cột nhân viên và cột ngày giờ (hoặc ngày + giờ): ZKTeco, Ronald Jack, Wise Eye, Hikvision CSV… File Excel cần lưu thành CSV trước (hoặc chuyển bằng /v1/xlsx-convert).
Ca đêm được tính thế nào?
Ca như 22:00–06:00 thuộc ngày bắt đầu ca; các lần chấm đến hết giờ ra cộng ot_window_hours (8 giờ) đều thuộc ca đó.
Ngày lễ có được tính tự động không?
Có, ngày lễ Việt Nam lấy từ /v1/vn-holidays (theo lịch nghỉ chính thức khi đã công bố). Gửi holidays để dùng lịch riêng của công ty, hoặc none.
API liên quan
Kiểm tra JSON
Kiểm tra cú pháp JSON, báo đúng dòng và cột bị lỗi, và validate dữ liệu theo JSON Schema (draft 4, 7, 2019-09 hoặc 2020-12).
{ }Định dạng JSON
Làm đẹp JSON với thụt lề 0-8 dấu cách hoặc tab, rút gọn (minify) hoặc sắp xếp key theo bảng chữ cái. Báo lỗi cú pháp kèm dòng và cột.
CSVCSV sang JSON
Chuyển CSV thành mảng object JSON theo dòng tiêu đề, tự nhận dấu phân cách, tự chuyển số và boolean, báo lỗi từng dòng.