Days, punches, and the requests that correct them. Read the attendance settings before interpreting any record — a late_minutes of 20 means nothing until you know the grace period was 15.
List attendance records
GET/v1/attendance_records
Query parameters
| Name | Type | Required | Description |
|---|
limit | integer | No | Page size. Values above 100 are clamped. |
starting_after | string | No | Opaque cursor from a previous response’s next_cursor. |
updated_since | timestamp | No | Return records changed at or after this instant. Tracks the record itself, not its child collections. |
employee_id | string | No | Only records belonging to this employee. |
date_from | date | No | Inclusive lower bound on the record's own date. |
date_to | date | No | Inclusive upper bound — the named day is included. |
status | string (enum) | No | Only days with this status. |
Responses
| Status | Meaning |
|---|
200 | A page of attendance records. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Mark attendance
POST/v1/attendance_records
Marks one day for one employee. There is at most one record per (employee, date), so this REPLACES an existing day rather than adding a second one — which is why it answers 200 and not 201.
Unless is_manual_override is set, a status the punches contradict is re-graded by the workspace's own late thresholds: sending present for a day with a two-hour late clock-in can come back as absent. That is usually what you want, and occasionally the opposite.
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | No | A unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true. |
Responses
| Status | Meaning |
|---|
200 | The resulting attendance record. |
400 | The request body failed validation. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
409 | The request conflicts with the current state. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Retrieve an attendance record
GET/v1/attendance_records/{id}
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The attendance record. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance record in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
List attendance punches
GET/v1/attendance_punches
Query parameters
| Name | Type | Required | Description |
|---|
limit | integer | No | Page size. Values above 100 are clamped. |
starting_after | string | No | Opaque cursor from a previous response’s next_cursor. |
employee_id | string | No | Only records belonging to this employee. |
punch_type | in · out | No | Only clock-ins, or only clock-outs. |
punched_after | timestamp | No | Inclusive lower bound on punch_time. |
punched_before | timestamp | No | Exclusive upper bound on punch_time. |
Responses
| Status | Meaning |
|---|
200 | A page of attendance punches. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Create an attendance punch
POST/v1/attendance_punches
Records a punch and applies it to the day, exactly as a device punch is applied — attribution date, lateness grading and the checkout window all behave identically.
punch_time may be backdated, since a time clock that lost connectivity has to be able to push what it buffered. It may not be post-dated.
A punch that changes no attendance record answers 409, not 201: a clock-in when the employee is already clocked in, a clock-out with no open record, or a clock-out past the checkout window. The punch is still written to the log in every one of those cases, so a 409 here means "the punch was kept but the day did not move", never "nothing happened".
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | No | A unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true. |
Responses
| Status | Meaning |
|---|
201 | The resulting attendance punch. |
400 | The request body failed validation. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
409 | The punch was recorded in the log but changed no attendance record. detail says which case applied. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Retrieve an attendance punch
GET/v1/attendance_punches/{id}
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The attendance punch. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance punch in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Retrieve the attendance settings
GET/v1/attendance_settings
A workspace singleton, so there is no id. Read-only: these rules change how existing pay is calculated, which is not something an integration should be able to do in a single call.
Read it before interpreting any attendance record — a late_minutes of 20 means nothing until you know the grace period was 15.
Responses
| Status | Meaning |
|---|
200 | The settings. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
List attendance regularizations
GET/v1/attendance_regularizations
Query parameters
| Name | Type | Required | Description |
|---|
limit | integer | No | Page size. Values above 100 are clamped. |
starting_after | string | No | Opaque cursor from a previous response’s next_cursor. |
updated_since | timestamp | No | Return records changed at or after this instant. Tracks the record itself, not its child collections. |
employee_id | string | No | Only records belonging to this employee. |
status | pending · approved · rejected | No | Only requests in this state. |
date_from | date | No | Inclusive lower bound on the record's own date. |
date_to | date | No | Inclusive upper bound — the named day is included. |
Responses
| Status | Meaning |
|---|
200 | A page of attendance regularizations. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Create an attendance regularization
POST/v1/attendance_regularizations
Asks to correct one day's attendance. Refused for an employee whose shift does not require punches — there is no missing-punch state to fix.
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | No | A unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true. |
Responses
| Status | Meaning |
|---|
201 | The resulting attendance regularization. |
400 | The request body failed validation. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
409 | A regularisation for this employee and date is already awaiting a decision. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Retrieve an attendance regularization
GET/v1/attendance_regularizations/{id}
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The attendance regularization. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance regularization in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Approve an attendance regularization
POST/v1/attendance_regularizations/{id}/approve
Approving REWRITES that day's attendance record and stamps it source: regularization, which then protects it from the automatic recompute. Answers 409 if the request was already decided.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The decided attendance regularization. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance regularization in this workspace. |
409 | This request has already been decided. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Reject an attendance regularization
POST/v1/attendance_regularizations/{id}/reject
Approving REWRITES that day's attendance record and stamps it source: regularization, which then protects it from the automatic recompute. Answers 409 if the request was already decided.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The decided attendance regularization. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance regularization in this workspace. |
409 | This request has already been decided. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
List overtime requests
GET/v1/overtime_requests
Query parameters
| Name | Type | Required | Description |
|---|
limit | integer | No | Page size. Values above 100 are clamped. |
starting_after | string | No | Opaque cursor from a previous response’s next_cursor. |
updated_since | timestamp | No | Return records changed at or after this instant. Tracks the record itself, not its child collections. |
employee_id | string | No | Only records belonging to this employee. |
status | pending · approved · rejected | No | Only requests in this state. |
date_from | date | No | Inclusive lower bound on the record's own date. |
date_to | date | No | Inclusive upper bound — the named day is included. |
Responses
| Status | Meaning |
|---|
200 | A page of overtime requests. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Create an overtime request
POST/v1/overtime_requests
Claims overtime for one day. A workspace with auto-approval enabled returns the request already approved.
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | No | A unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true. |
Responses
| Status | Meaning |
|---|
201 | The resulting overtime request. |
400 | The request body failed validation. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
409 | An overtime request for this employee and date is already awaiting a decision. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Retrieve an overtime request
GET/v1/overtime_requests/{id}
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The overtime request. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such overtime request in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Approve an overtime request
POST/v1/overtime_requests/{id}/approve
Whether approval is what makes the minutes count toward pay depends on overtime_require_approval in the attendance settings. Answers 409 if the request was already decided.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The decided overtime request. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such overtime request in this workspace. |
409 | This request has already been decided. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Reject an overtime request
POST/v1/overtime_requests/{id}/reject
Whether approval is what makes the minutes count toward pay depends on overtime_require_approval in the attendance settings. Answers 409 if the request was already decided.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The decided overtime request. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such overtime request in this workspace. |
409 | This request has already been decided. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
List rest day swaps
GET/v1/rest_day_swaps
Query parameters
| Name | Type | Required | Description |
|---|
limit | integer | No | Page size. Values above 100 are clamped. |
starting_after | string | No | Opaque cursor from a previous response’s next_cursor. |
updated_since | timestamp | No | Return records changed at or after this instant. Tracks the record itself, not its child collections. |
employee_id | string | No | Only records belonging to this employee. |
Responses
| Status | Meaning |
|---|
200 | A page of rest day swaps. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Create a rest day swap
POST/v1/rest_day_swaps
worked_date must be a rest day for that employee — a weekly off or a holiday — off_date must be an ordinary working day, and both must fall in the same calendar month.
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | No | A unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true. |
Responses
| Status | Meaning |
|---|
201 | The resulting rest day swap. |
400 | The request body failed validation. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
409 | One of the dates is already part of another swap. A rest day can be swapped once, and a substitute day can absorb one swap. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Retrieve a rest day swap
GET/v1/rest_day_swaps/{id}
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The rest day swap. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such rest day swap in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Delete a rest day swap
DELETE/v1/rest_day_swaps/{id}
Removes the swap, restoring both days to their ordinary classification.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The deleted rest day swap, so you have what was removed. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such rest day swap in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
List employee shifts
GET/v1/employee_shifts
Query parameters
| Name | Type | Required | Description |
|---|
limit | integer | No | Page size. Values above 100 are clamped. |
starting_after | string | No | Opaque cursor from a previous response’s next_cursor. |
employee_id | string | No | Only records belonging to this employee. |
shift_id | string | No | Only assignments of this shift. |
current | boolean | No | Only the assignment in force today. |
Responses
| Status | Meaning |
|---|
200 | A page of employee shifts. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Create an employee shift
POST/v1/employee_shifts
Assigns a shift from a date, closing any open assignment the day before this one starts.
Worth doing straight after creating an employee. Employee creation does not assign a shift, and an employee without one has no expected hours — so attendance has nothing to grade against and payroll cannot classify their days.
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | No | A unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true. |
Responses
| Status | Meaning |
|---|
201 | The resulting employee shift. |
400 | The request body failed validation. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
409 | The request conflicts with the current state. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Retrieve an employee shift
GET/v1/employee_shifts/{id}
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The employee shift. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such employee shift in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Delete an employee shift
DELETE/v1/employee_shifts/{id}
Removes the assignment and recomputes attendance over the period it covered, so any grading that depended on it resolves again.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The deleted employee shift, so you have what was removed. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such employee shift in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
List attendance sites
GET/v1/attendance_sites
Query parameters
| Name | Type | Required | Description |
|---|
limit | integer | No | Page size. Values above 100 are clamped. |
starting_after | string | No | Opaque cursor from a previous response’s next_cursor. |
updated_since | timestamp | No | Return records changed at or after this instant. Tracks the record itself, not its child collections. |
status | active · inactive | No | Only sites in this state. |
Responses
| Status | Meaning |
|---|
200 | A page of attendance sites. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Create an attendance site
POST/v1/attendance_sites
Creates a geofenced site. radius_meters defaults to 150 and is bounded to 10–10000, matching what the app itself accepts.
A site with no assigned employees accepts no punches — see the assignments sub-resource.
| Name | Type | Required | Description |
|---|
Idempotency-Key | string | No | A unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true. |
Responses
| Status | Meaning |
|---|
201 | The resulting attendance site. |
400 | The request body failed validation. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
409 | The request conflicts with the current state. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Retrieve an attendance site
GET/v1/attendance_sites/{id}
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The attendance site. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance site in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Update an attendance site
PATCH/v1/attendance_sites/{id}
Only the fields present in the body are changed. branch_id: null detaches the site from its branch.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The updated attendance site. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance site in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Delete an attendance site
DELETE/v1/attendance_sites/{id}
Permanent. Assignments go with it; punch-attempt history survives with the site reference cleared.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The deleted attendance site, so you have what was removed. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance site in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
List the employees assigned to a site
GET/v1/attendance_sites/{id}/assignments
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The assigned employee ids. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance site in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |
Replace the employees assigned to a site
PUT/v1/attendance_sites/{id}/assignments
Send the COMPLETE list, not a delta — it replaces whatever was assigned. An empty array unassigns everyone, which leaves the site accepting no punches.
Path parameters
| Name | Type | Required | Description |
|---|
id | string | Yes | The identifier returned as id on the object. |
Responses
| Status | Meaning |
|---|
200 | The assigned employee ids after the change. |
400 | One of the employees is not in this workspace. |
401 | The API key is missing, malformed, revoked or expired. |
403 | The key does not carry the required scopes. |
404 | No such attendance site in this workspace. |
429 | Rate limit exceeded. See the RateLimit-* headers. |