Dùng token kết nối, dưới /v1/work. Dành cho tổ chức ghi sổ lương ở một hệ thống khác (phần mềm kế toán, ERP): mỗi phiếu lương đã chốt trong CTAS Work được mang sang dưới dạng số tổng, và hệ thống đó báo lại khi đã chi.
Ứng dụng làm theo luật của bảng lương CTAS Work, không có luật riêng. Chốt, duyệt, mở lại vẫn do người trong CTAS Work làm. Ứng dụng chỉ đọc, và chỉ đánh dấu đã chi cho phiếu đã được duyệt.
Bốn bước của một phiếu
state | Nghĩa |
|---|---|
closed | đã chốt và gửi cho nhân viên; số đã cố định |
verified | quản lý đã duyệt |
paid | đã chi — xong hẳn, không mở lại được |
reopened | đang mở lại để tính lại; totals là null, chờ chốt lại |
Nhân viên xác nhận phiếu không chặn bước nào nên chỉ nằm ở confirmed_at. Phiếu đã duyệt có thể bị bỏ duyệt (thêm khoản cộng/trừ) hoặc mở lại cho đến khi đã chi.
Đọc phiếu
GET /payslips?period=2026-09&state=&member=&limit=&cursor= — quyền payroll:read. Mặc định trả mọi phiếu đã chốt của kỳ. GET /payslips/{id} — một phiếu, kể cả phiếu đang mở lại.
{ "id": "psl_…", "member_id": "mem_…", "department_id": "dep_…", "period": "2026-09",
"pay_date": "2026-10-05", "state": "verified",
"closed_at": "…", "confirmed_at": "…", "verified_at": "…", "paid_at": null, "paid_via": null,
"currency": "VND",
"totals": { "income": 9800000, "deductions": 50000, "insurance": 840000, "tax": 0,
"advances": 1000000, "net": 7910000, "company_insurance": 1720000 } }
- Không có từng dòng của phiếu. Mỗi dòng rơi vào đúng một nhóm nên luôn có
income − deductions − insurance − tax − advances = net, khớp tới đồng. taxlà thuế TNCN đã khấu trừ, bằng0khi tổ chức chưa bật thuế.advanceslà tạm ứng thu hồi trong kỳ.company_insurancelà phần bảo hiểm công ty đóng, không nằm trong thực lĩnh.
Lương theo nơi làm
Mỗi phiếu kèm allocation: thu nhập, khoản trừ và BH công ty đóng theo phòng ban nơi tiền được làm ra — để hạch toán chi phí lương đúng cửa hàng.
"allocation": { "basis": "closed", "home_department_id": "dep_A",
"departments": [
{ "department_id": "dep_A", "department_name": "Thăng Long", "home": true, "income": 6400000, "deductions": 50000, "company_insurance": 840000,
"days": null, "hours": null, "shifts": null },
{ "department_id": "dep_B", "department_name": "Bàn Cờ", "home": false, "income": 1600000, "deductions": 0, "company_insurance": 0,
"days": 4, "hours": 32, "shifts": 4 } ] }
- Ca được xếp ở phòng khác (nơi làm việc = phòng ban khác) tính về phòng đó: lương công/giờ của ngày đó, tăng ca, ca có giá riêng, khoản ghi trên ca.
- Ở lại phòng của người: phụ cấp, thưởng, phạt theo kỳ, khoản thêm tay, ngày nghỉ có lương, lễ, công tác, BH công ty đóng. Chấm công ở nơi khác mà không xếp ca cũng tính về phòng của người.
- Phần BH, thuế, tạm ứng của người lao động không chia (không phải chi phí của nơi nào).
- Cộng các phòng luôn ra đúng
totals.income,totals.deductions,totals.company_insurance. basis = closed: chia lúc chốt, đóng băng cùng phiếu.recomputed: phiếu chốt trước 12/10/2026, tính lại sau theo lịch hiện có.allocation = null: chưa tính được (phiếu cũ chưa tính lại, hoặc đang mở lại).
Đánh dấu đã chi
POST /payslips/{id}/pay — quyền payroll:write. Chỉ cho phiếu đã duyệt:
| Lỗi | Khi nào |
|---|---|
409 PAYSLIP_NOT_VERIFIED | phiếu chưa được duyệt |
409 PAYSLIP_REOPENED | phiếu đang mở lại |
Gọi lại phiếu đã chi trả về phiếu như hiện tại (an toàn khi thử lại). Phiếu ghi paid_via là tên ứng dụng của bạn, nhân viên nhận thông báo "đã được chi" như khi chi trong CTAS Work. Kết nối của bạn không nhận payslip.paid cho chính lần đánh dấu này.
Sự kiện
payslip.closed, payslip.reopened, payslip.verified, payslip.unverified, payslip.paid, payslip.deleted.
{ "payslip_id": "psl_…", "member_id": "mem_…", "period": "2026-09", "state": "verified" }
Webhook không kèm số tiền: nhận sự kiện rồi đọc lại phiếu bằng GET /payslips/{id}. Cách đồng bộ gợi ý: nhận phiếu khi verified, gỡ khi unverified/reopened/deleted, ghi đã chi khi paid; định kỳ quét GET /payslips?period= để bù sự kiện lỡ.
CTAS Developer