Attendance timesheet API
Turn time-clock exports into a timesheet: worked hours and units per day, late / early minutes, missing punches, OT by day type and night hours (22h-6h).
Send the punches exported from a time clock (ZKTeco, Ronald Jack, Wise Eye… as CSV, or JSON) and your shifts. Columns are detected from usual headers (AC-No., Mã NV, Name, Họ tên, Time, Thời gian, Ngày + Giờ, several times in one cell) or set with columns; dates are read as dd/mm/yyyy unless date_format=mdy / ymd. Shifts have a start, an end (a night shift ending the next morning is fine), a break and grace minutes for late arrival and early leave.
Each employee-day gets the shift whose start is nearest the first punch, first in and last out, late and early-leave minutes, worked minutes without the break and work units (công), a missing punch flag, overtime after the shift (from ot_min_minutes, optionally rounded), and night minutes between 22:00 and 06:00 (Labour Code 2019, Điều 106). On weekly rest days (rest_days, Sunday by default) and public holidays (computed by /v1/vn-holidays, or your own holidays) all time worked is overtime of that type.
The summary per employee gives days and units, hours, late / early counts, missing punches, absent workdays, overtime split into workday / rest day / holiday (paid at least 150% / 200% / 300%, Điều 98) and night overtime, with a warning above 40 hours of overtime in a month (Điều 107). Pay rates are not applied, so the result feeds any payroll.
Parameters
| Name | In | Type | Required | Default | |
|---|---|---|---|---|---|
csv | body | string | no | Attendance log as CSV / TSV text (or logs JSON array, or a CSV file). | |
logs | body | array | no | Rows such as [{"employee":"1","time":"2026-11-02 07:58"}]. | |
columns | body | object | no | Column mapping: employee, name, datetime or date + time. | |
shifts | body | array | no | Shifts [{"code","start","end","break_start","break_end","grace_late","grace_early"}] (default 08:00-17:00, break 12-13). | |
from | body | string | no | Period start (YYYY-MM-DD) for absences and standard workdays. | |
to | body | string | no | Period end (YYYY-MM-DD). | |
rest_days | body | string | no | 0 | Weekly rest days, 0 = Sunday … 6 = Saturday, e.g. 6,0. |
holidays | body | array | no | Your holiday dates (default: Vietnamese public holidays), or none. | |
ot_min_minutes | body | number | no | 30 | Minimum overtime counted after a shift. |
ot_round_minutes | body | number | no | 0 | Round overtime down to this step (e.g. 15). |
date_format | body | string | no | dmy | dmy, mdy or ymd for slash dates. |
Example
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));Response
{
"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"
}
Use cases
- Compute monthly attendance for an SME payroll from time-clock exports
- Show late / early statistics in an HR dashboard
- Split overtime hours by rate before salary calculation
- Check overtime against the 40-hour monthly limit
FAQ
Which time clocks are supported?
Any export that has an employee column and date-time (or date + time) columns: ZKTeco, Ronald Jack, Wise Eye, Hikvision CSV… Excel files must be saved as CSV first (or converted with /v1/xlsx-convert).
How are night shifts handled?
A shift such as 22:00–06:00 belongs to the day it starts; punches up to the shift end plus ot_window_hours (8 h) belong to it.
Are holidays counted automatically?
Yes, Vietnamese public holidays come from /v1/vn-holidays (official schedules where announced). Pass holidays with your company’s dates, or none.
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.