CloudPay API
Read employees, leave, attendance and payroll summaries from your other systems, file leave requests and record clock punches.
- Base URL
https://cloudpay.cloudbox8.com/api/v1- Authentication
- An API key from Settings › Integrations › Developers, sent as
Authorization: Bearer cpk_…. It opens only its scopes. - Rate limit
- 120 requests a minute per key unless set otherwise. Answers carry
X-RateLimit-*headers; past the limit, 429 withRetry-After. - Errors
{ "error": "…", "code": "…" }with the HTTP status. Lists takepageandpageSize(up to 200).- Privacy
- NIC, passport, work permit, bank account, address and medical details are never returned. Salaries need payroll:read.
curl https://cloudpay.cloudbox8.com/api/v1/employees \ -H "Authorization: Bearer cpk_…"OpenAPI 3.1 document (openapi.json)
Employees
The people of your company.
GET/employeesList employeesemployees:read
Active employees by default, ordered by employee number. Pass `status=all` (or one status) for the others.
Scope
employees:read— read employees.Parameters
statusone of ACTIVE, ON_LEAVE, SUSPENDED, TERMINATED, RESIGNED, all- An employee status, or `all`. Default ACTIVE.
departmentIdstringlocationIdstringupdatedSincedate-time- Only rows changed at or after this instant
pageinteger- Page number, from 1
pageSizeinteger- Rows per page
GET/employees/{id}Get an employeeemployees:read
By CloudPay id or employee number.
Scope
employees:read— read employees.Parameters
idstring · required- Employee id or employee number
Leave
Leave types, balances and requests.
GET/leave/typesList leave typesleave:read
The leave types a request can name, by id or code.
Scope
leave:read— read leave.GET/leave/balancesList leave balancesleave:read
The balances of one leave year — the calendar year its validity window starts in — for the company or one employee.
Scope
leave:read— read leave.Parameters
yearinteger- Leave year. Default: the current year.
employeeIdstring- One employee, by CloudPay id
employeeNostring- One employee, by employee number
leaveTypeIdstringpageinteger- Page number, from 1
pageSizeinteger- Rows per page
GET/leave/requestsList leave requestsleave:read
Newest first. `from` / `to` return the requests that touch the period.
Scope
leave:read— read leave.Parameters
statusone of PENDING, SUPERVISOR_APPROVED, APPROVED, REJECTED, CANCELLED, OPEN- OPEN = awaiting a decision at either step.
employeeIdstring- One employee, by CloudPay id
employeeNostring- One employee, by employee number
fromdatetodateupdatedSincedate-time- Only rows changed at or after this instant
pageinteger- Page number, from 1
pageSizeinteger- Rows per page
POST/leave/requestsRequest leave for an employeeleave:write
Files a request as HR would on the employee's behalf: CloudPay counts the working days (work week and public holidays), checks the balance and overlapping requests, and refuses days of a closed pay period. The request then waits for approval in CloudPay. A full day, half a day, or a number of hours on one day.
Scope
leave:write— request leave.JSON body
employeeIdstring- Give employeeId or employeeNo
employeeNostringleaveTypeIdstring- Give leaveTypeId or leaveTypeCode
leaveTypeCodestringstartDatedate · requiredendDatedate · requiredisHalfDaybooleanhalfDayPeriodone of MORNING, AFTERNOONhoursnumber- Hourly leave on one day: the hours off (or startTime / endTime)
startTimestring- HH:MM
endTimestring- HH:MM
reasonstring
GET/leave/requests/{id}Get a leave requestleave:read
Follow a request you filed until it is decided.
Scope
leave:read— read leave.Parameters
idstring · required- In the path
Attendance
Clock-in and clock-out punches.
GET/attendance/punchesList punchesattendance:read
One record per shift, with its clock-in and clock-out and the hours they make, for at most 31 days (default: the last 7). Days without a clock-in are left out. A day can have two records: an Office + WFH day has an office part and a work-from-home part (`place`, `splitDay`, `dayShare`).
Scope
attendance:read— read attendance.Parameters
fromdatetodateemployeeIdstring- One employee, by CloudPay id
employeeNostring- One employee, by employee number
updatedSincedate-time- Only rows changed at or after this instant
pageinteger- Page number, from 1
pageSizeinteger- Rows per page
POST/attendance/punchesRecord a punchattendance:write
A clock-in or clock-out from a time clock, badge reader or another system, at most 7 days old. Send punches in the order they happened. Without `direction` the punch clocks out an employee who is clocked in and clocks in one who is not. The same punch sent again within 2 minutes — even after the shift has closed — is answered with `duplicate: true` and changes nothing; a clock-in that would overlap a recorded shift is refused with 409 OUT_OF_ORDER. Hours are worked out like a clock-out in the app (break, overtime, meal allowance).
Scope
attendance:write— record punches.JSON body
employeeIdstring- Give employeeId or employeeNo
employeeNostringtimestampdate-time · required- When the punch happened, with its offset (e.g. 2026-10-18T08:02:11+04:00)
directionone of IN, OUT- Omit to let CloudPay decide from the employee's open session
methodone of FINGERPRINT, QR_CODE, MANUAL · required- How the employee punched: FINGERPRINT, QR_CODE, or MANUAL for any other terminal
locationIdstring- The site the terminal is at (default: the roster's, else the employee's)
notestring
Time terminals
Punches from badge, fingerprint and card terminals, sent with the terminal's device key.
POST/punchesSend terminal punchesdevice key
One punch, or `{ "punches": [...] }` up to 200 (a terminal flushing its buffer), each naming the employee by `badgeNumber` (or `employeeNo` / `employeeId`) with its time — ISO 8601 with an offset, or the terminal's local time without one, read as Mauritius time. Without `direction`, CloudPay pairs the punches: one closes the open shift, else opens one; a lone punch nearer the end of the shift than its start, with nothing open, is left for HR (IGNORED, UNPAIRED). The same punch within 2 minutes, or a record id (`externalId`) sent before, is a DUPLICATE and changes nothing. Each result says APPLIED, DUPLICATE, IGNORED (REGULARISED, UNPAIRED) or REJECTED (UNKNOWN_BADGE, NO_ACCESS, EMPLOYEE_NOT_ACTIVE, PERIOD_CLOSED, OUT_OF_ORDER…), in the order sent.
Sent by a time terminal with its own device key (
Bearer cpd_…, Settings › Integrations › Time terminals), not an API key.
Payroll
Payroll run summaries. Needs the Payroll module.
GET/payroll/runsList payroll runspayroll:read
Run summaries, newest period first. Cancelled runs only when asked for with `status=CANCELLED`.
Scope
payroll:read— read payroll.Parameters
yearinteger- Pay year
monthinteger- Pay month (1–12): the month the period ends in
statusone of DRAFT, PROCESSING, PROCESSED, APPROVED, PAID, CANCELLEDrunTypeone of REGULAR, OFF_CYCLE, BONUSpageinteger- Page number, from 1
pageSizeinteger- Rows per page
GET/payroll/runs/{id}Get a payroll runpayroll:read
The run's summary and each employee's totals: gross, deductions, net and employer cost.
Scope
payroll:read— read payroll.Parameters
idstring · required- In the path