Skip to main content
If payroll runs somewhere other than OnTime, this is the integration you need: a month of day records, per employee, in whatever shape your payroll system imports.

What you are pulling

GET /api/public/v1/attendance?date=YYYY-MM-DD returns one date, all employees:
There is no date-range endpoint. A month means 28–31 requests, one per date. At 600 requests per minute this is comfortable, but do it sequentially with a small delay rather than firing thirty concurrent requests.

Timing matters more than the code

Only export closed days. A day is finalized by the nightly close, which runs after the day is over. Crucially, Absent is never written to a day still in progress — so exporting a month that includes today under-counts absences silently.Export a completed month, and do it at least a day after the month ends.
Better still, export after the OnTime payroll cycle for that month has been frozen. A frozen day cannot re-derive, so your export is reproducible: re-running it produces the same numbers.

The script

Getting the paid-days rule right

The aggregation above treats everything except Absent as paid. That is the common case, but check it against your payroll rules:
The unpaid-leave gap is the one to design around. status: "Leave" covers both paid leave and Loss of Pay, and the public attendance endpoint does not expose the leave type.If unpaid leave types are in use, this export will over-count paid days. Either restrict LOP handling to OnTime’s own payroll, or reconcile against leave data pulled separately.
There is also a known boundary quirk in how the last calendar day of a month is captured by OnTime’s own attendance-window query. Spot-check month-end totals against a day report the first time you run this.

Making it repeatable

1

Export after the month is frozen

Reproducible numbers.
2

Store the raw daily responses, not just the summary

When payroll disputes a figure, you want the day it came from.
3

Re-export rather than accumulate

An approved regularization rewrites a past day. A monthly re-read picks that up; a running daily total does not.
4

Subscribe to regularization.approved

So you know a past day changed and can re-export that month. See Events.