Batch Payroll & Payslips (VN) API
Payroll for a whole company: gross or net per employee, allowances, dependents, insurance caps, PIT, employer cost, totals, XLSX sheet and PDF payslips.
Send the staff list as JSON (employees) or upload a CSV / XLSX file with a header row (Vietnamese headers such as "Họ tên", "Lương", "Số NPT", "Vùng", "Lương đóng BH" are recognised). Each row is computed with the same rules as vn-salary: employee social, health and unemployment insurance (8 / 1.5 / 1 %) on the insurance salary capped at 20 × the base salary (2,530,000 VND from 1/7/2026) and 20 × the regional minimum wage, family deductions of 15.5 million + 6.2 million per dependent and the 5-bracket PIT table from 2026, and the employer share (17 % + 0.5 % + 3 % + 1 %, optional 2 % union fund).
Rows can be gross (salary / gross) or net (net: the gross is solved), prorated by work_days / standard_days, with bonus, overtime (tax-free part), advances and other deductions. Allowances come as allowances (array of { name, amount, taxable, insurance }) or as columns prefixed pc_ (taxable), pckct_ (tax-free) or pcbh_ (in the insurance salary); allowance_rules reclassifies them by name. Tax-free caps are not applied automatically: you decide what is exempt.
format=json returns every row and column totals; format=xlsx a ready-to-print payroll sheet ("Bảng thanh toán tiền lương", Times New Roman, totals and signature lines); format=payslips a ZIP with one A5 PDF payslip per employee in Vietnamese or English (Be Vietnam Pro font). Limits: 2,000 rows, 200 payslips per request. Files are processed in memory and not stored.
Parameters
| Name | In | Type | Required | Default | |
|---|---|---|---|---|---|
employees | body | array | yes | Employees: [{ name, employee_id?, department?, position?, salary | gross | net, dependents?, region?, insurance_salary?, allowances?, work_days?, bonus?, overtime?, advance?, … }]. Or upload file (CSV / XLSX). | |
file | body | file | no | CSV or XLSX with a header row (multipart). | |
period | body | string | no | Payroll month YYYY-MM (default: this month). Rules of that month apply. | |
mode | body | string | no | gross | Default for rows with salary: gross or net. |
region | body | number | no | 1 | Default minimum-wage region 1–4. |
standard_days | body | number | no | 26 | Standard work days for proration. |
allowance_rules | body | object | no | { "Ăn trưa": { "taxable": false, "insurance": false } } to classify allowances by name. | |
union_fund | body | boolean | no | false | Add the 2 % union fund to the employer cost. |
format | body | string | no | json | json, xlsx (payroll sheet) or payslips (ZIP of PDFs). |
company | body | string | no | Company name printed on the sheet and payslips. | |
lang | body | string | no | vi | Payslip language: vi or en. |
Example
curl -X POST "https://apibox.io.vn/v1/vn-payroll-batch" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"period":"2026-11","employees":[{"employee_id":"NV01","name":"Nguyễn Văn An","department":"Kế toán","salary":30000000},{"employee_id":"NV02","name":"Trần Thị Bình","salary":20000000,"dependents":1,"insurance_salary":15000000,"allowances":[{"name":"Ăn trưa","amount":730000,"taxable":false},{"name":"Điện thoại","amount":500000}]}]}'const res = await fetch('https://apibox.io.vn/v1/vn-payroll-batch', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"period": "2026-11",
"employees": [
{
"employee_id": "NV01",
"name": "Nguyễn Văn An",
"department": "Kế toán",
"salary": 30000000
},
{
"employee_id": "NV02",
"name": "Trần Thị Bình",
"salary": 20000000,
"dependents": 1,
"insurance_salary": 15000000,
"allowances": [
{
"name": "Ăn trưa",
"amount": 730000,
"taxable": false
},
{
"name": "Điện thoại",
"amount": 500000
}
]
}
]
}),
});
const data = await res.json();
console.log(data);import requests
res = requests.post(
"https://apibox.io.vn/v1/vn-payroll-batch",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"period": "2026-11", "employees": [{"employee_id": "NV01", "name": "Nguyễn Văn An", "department": "Kế toán", "salary": 30000000}, {"employee_id": "NV02", "name": "Trần Thị Bình", "salary": 20000000, "dependents": 1, "insurance_salary": 15000000, "allowances": [{"name": "Ăn trưa", "amount": 730000, "taxable": False}, {"name": "Điện thoại", "amount": 500000}]}]},
timeout=30,
)
print(res.json())<?php
$ch = curl_init('https://apibox.io.vn/v1/vn-payroll-batch');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"period":"2026-11","employees":[{"employee_id":"NV01","name":"Nguyễn Văn An","department":"Kế toán","salary":30000000},{"employee_id":"NV02","name":"Trần Thị Bình","salary":20000000,"dependents":1,"insurance_salary":15000000,"allowances":[{"name":"Ăn trưa","amount":730000,"taxable":false},{"name":"Điện thoại","amount":500000}]}]}',
]);
$response = curl_exec($ch);
print_r(json_decode($response, true));Response
{
"period": "2026-11",
"source": "json",
"mode": "gross",
"employees": 2,
"totals": {
"base_salary": 50000000,
"allowances_total": 1230000,
"bonus": 0,
"overtime": 0,
"gross": 51230000,
"insurance_salary": 45000000,
"bhxh": 3600000,
"bhyt": 675000,
"bhtn": 450000,
"non_taxable_income": 730000,
"family_deduction": 37200000,
"taxable_income": 11350000,
"pit": 635000,
"net": 45870000,
"advance": 0,
"other_deductions": 0,
"take_home": 45870000,
"er_bhxh": 7650000,
"er_tnld": 225000,
"er_bhyt": 1350000,
"er_bhtn": 450000,
"er_union": 0,
"employer_cost": 60905000,
"employee_insurance": 4725000,
"employer_insurance": 9675000
},
"rows": [
{
"no": 1,
"employee_id": "NV01",
"name": "Nguyễn Văn An",
"department": "Kế toán",
"position": null,
"email": null,
"bank_account": null,
"mode": "gross",
"region": 1,
"dependents": 0,
"resident": true,
"work_days": null,
"standard_days": null,
"base_salary": 30000000,
"allowances": [],
"allowances_total": 0,
"bonus": 0,
"overtime": 0,
"gross": 30000000,
"insurance_salary": 30000000,
"employee_insurance": {
"bhxh": 2400000,
"bhyt": 450000,
"bhtn": 300000,
"total": 3150000
},
"non_taxable_income": 0,
"personal_deduction": 15500000,
"dependent_deduction": 0,
"taxable_income": 11350000,
"pit": 635000,
"net": 26215000,
"advance": 0,
"other_deductions": 0,
"take_home": 26215000,
"employer": {
"bhxh": 5100000,
"tnld_bnn": 150000,
"bhyt": 900000,
"bhtn": 300000,
"union_fund": 0,
"total": 6450000
},
"employer_cost": 36450000,
"warnings": []
}
],
"rules": {
"personal_deduction": 15500000,
"dependent_deduction": 6200000,
"deduction_ref": "Nghị quyết 110/2025/UBTVQH15",
"tax_table": "Luật Thuế TNCN 109/2025/QH15 (5 bậc)",
"base_salary": 2530000,
"base_salary_ref": "Nghị định 161/2026/NĐ-CP",
"insurance_cap_bhxh_bhyt": 50600000,
"region_min_wage": [
5310000,
4730000,
4140000,
3700000
],
"region_min_wage_ref": "Nghị định 293/2025/NĐ-CP",
"employee_rates": {
"bhxh": 0.08,
"bhyt": 0.015,
"bhtn": 0.01
},
"employer_rates": {
"bhxh": 0.17,
"tnld_bnn": 0.005,
"bhyt": 0.03,
"bhtn": 0.01,
"union_fund": 0
},
"allowances": "Allowances are taxable and outside the insurance salary unless classified (non_t…"
},
"legal": "Luật Thuế TNCN 109/2025/QH15 and NQ 110/2025/UBTVQH15 (from tax year 2026); Luật BHXH 41/2024/QH15, Luật BHYT, Luật Việc làm (rates and 20× caps); NĐ 161/2026/NĐ-CP (base salary 2,530,000 from 1/7/2026); NĐ 293/2025/NĐ-CP (regional minimum wages 2026).",
"reviewed": "2026-11-11",
"disclaimer": "Reference calculation, not legal advice; check the official text."
}
Use cases
- Run the monthly payroll of an SME from an Excel list
- Send every employee a PDF payslip
- Estimate the total employer cost of a hiring plan
- Check an HR system’s payroll against an independent calculation
FAQ
Which rules are used?
The rules in force in the payroll month: PIT under Luật 109/2025/QH15 and NQ 110/2025/UBTVQH15 from 2026, insurance under Luật BHXH 2024, base salary 2,530,000 VND from 1/7/2026, regional minimum wages of NĐ 293/2025/NĐ-CP.
Are meal or phone allowances tax-free?
Only if you mark them (taxable: false or a pckct_ column). The legal caps depend on your policies and invoices, so the API does not guess.
Can I protect payslips with a password?
Not yet: PDF encryption is not available in the Workers runtime. Send the ZIP over a private channel.
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.