Skip to main content

Attendance & time

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.

Plan feature

/v1/attendance_sites needs a plan that includes GPS attendance & field visits (geo_attendance). On a plan without it, requests return 402 with code: plan_upgrade_required and feature naming what an upgrade would add.

List attendance records​

GET/v1/attendance_records

Query parameters​

NameTypeRequiredDescription
limitintegerNoPage size. Values above 100 are clamped.
starting_afterstringNoOpaque cursor from a previous response’s next_cursor.
updated_sincetimestampNoReturn records changed at or after this instant. Tracks the record itself, not its child collections.
employee_idstringNoOnly records belonging to this employee.
date_fromdateNoInclusive lower bound on the record's own date.
date_todateNoInclusive upper bound — the named day is included.
statusstring (enum)NoOnly days with this status.

Responses​

StatusMeaning
200A page of attendance records.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
429Rate 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.

Headers​

NameTypeRequiredDescription
Idempotency-KeystringNoA unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true.

Responses​

StatusMeaning
200The resulting attendance record.
400The request body failed validation.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
409The request conflicts with the current state.
429Rate limit exceeded. See the RateLimit-* headers.

Retrieve an attendance record​

GET/v1/attendance_records/{id}

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The attendance record.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such attendance record in this workspace.
429Rate limit exceeded. See the RateLimit-* headers.

List attendance punches​

GET/v1/attendance_punches

Query parameters​

NameTypeRequiredDescription
limitintegerNoPage size. Values above 100 are clamped.
starting_afterstringNoOpaque cursor from a previous response’s next_cursor.
employee_idstringNoOnly records belonging to this employee.
punch_typein · outNoOnly clock-ins, or only clock-outs.
punched_aftertimestampNoInclusive lower bound on punch_time.
punched_beforetimestampNoExclusive upper bound on punch_time.

Responses​

StatusMeaning
200A page of attendance punches.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
429Rate 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".

Headers​

NameTypeRequiredDescription
Idempotency-KeystringNoA unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true.

Responses​

StatusMeaning
201The resulting attendance punch.
400The request body failed validation.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
409The punch was recorded in the log but changed no attendance record. detail says which case applied.
429Rate limit exceeded. See the RateLimit-* headers.

Retrieve an attendance punch​

GET/v1/attendance_punches/{id}

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The attendance punch.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such attendance punch in this workspace.
429Rate 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​

StatusMeaning
200The settings.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
429Rate limit exceeded. See the RateLimit-* headers.

List attendance regularizations​

GET/v1/attendance_regularizations

Query parameters​

NameTypeRequiredDescription
limitintegerNoPage size. Values above 100 are clamped.
starting_afterstringNoOpaque cursor from a previous response’s next_cursor.
updated_sincetimestampNoReturn records changed at or after this instant. Tracks the record itself, not its child collections.
employee_idstringNoOnly records belonging to this employee.
statuspending · approved · rejectedNoOnly requests in this state.
date_fromdateNoInclusive lower bound on the record's own date.
date_todateNoInclusive upper bound — the named day is included.

Responses​

StatusMeaning
200A page of attendance regularizations.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
429Rate 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.

Headers​

NameTypeRequiredDescription
Idempotency-KeystringNoA unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true.

Responses​

StatusMeaning
201The resulting attendance regularization.
400The request body failed validation.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
409A regularisation for this employee and date is already awaiting a decision.
429Rate limit exceeded. See the RateLimit-* headers.

Retrieve an attendance regularization​

GET/v1/attendance_regularizations/{id}

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The attendance regularization.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such attendance regularization in this workspace.
429Rate 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, or if it is the API key creator’s own and another approver can decide it.

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The decided attendance regularization.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such attendance regularization in this workspace.
409This request has already been decided, or it is the API key creator’s own and another approver can decide it.
429Rate 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, or if it is the API key creator’s own and another approver can decide it.

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The decided attendance regularization.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such attendance regularization in this workspace.
409This request has already been decided, or it is the API key creator’s own and another approver can decide it.
429Rate limit exceeded. See the RateLimit-* headers.

List overtime requests​

GET/v1/overtime_requests

Query parameters​

NameTypeRequiredDescription
limitintegerNoPage size. Values above 100 are clamped.
starting_afterstringNoOpaque cursor from a previous response’s next_cursor.
updated_sincetimestampNoReturn records changed at or after this instant. Tracks the record itself, not its child collections.
employee_idstringNoOnly records belonging to this employee.
statuspending · approved · rejectedNoOnly requests in this state.
date_fromdateNoInclusive lower bound on the record's own date.
date_todateNoInclusive upper bound — the named day is included.

Responses​

StatusMeaning
200A page of overtime requests.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
429Rate 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.

Headers​

NameTypeRequiredDescription
Idempotency-KeystringNoA unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true.

Responses​

StatusMeaning
201The resulting overtime request.
400The request body failed validation.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
409An overtime request for this employee and date is already awaiting a decision.
429Rate limit exceeded. See the RateLimit-* headers.

Retrieve an overtime request​

GET/v1/overtime_requests/{id}

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The overtime request.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such overtime request in this workspace.
429Rate 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, or if it is the API key creator’s own and another approver can decide it.

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The decided overtime request.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such overtime request in this workspace.
409This request has already been decided, or it is the API key creator’s own and another approver can decide it.
429Rate 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, or if it is the API key creator’s own and another approver can decide it.

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The decided overtime request.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such overtime request in this workspace.
409This request has already been decided, or it is the API key creator’s own and another approver can decide it.
429Rate limit exceeded. See the RateLimit-* headers.

List rest day swaps​

GET/v1/rest_day_swaps

Query parameters​

NameTypeRequiredDescription
limitintegerNoPage size. Values above 100 are clamped.
starting_afterstringNoOpaque cursor from a previous response’s next_cursor.
updated_sincetimestampNoReturn records changed at or after this instant. Tracks the record itself, not its child collections.
employee_idstringNoOnly records belonging to this employee.

Responses​

StatusMeaning
200A page of rest day swaps.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
429Rate 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.

Headers​

NameTypeRequiredDescription
Idempotency-KeystringNoA unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true.

Responses​

StatusMeaning
201The resulting rest day swap.
400The request body failed validation.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
409One of the dates is already part of another swap. A rest day can be swapped once, and a substitute day can absorb one swap.
429Rate limit exceeded. See the RateLimit-* headers.

Retrieve a rest day swap​

GET/v1/rest_day_swaps/{id}

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The rest day swap.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such rest day swap in this workspace.
429Rate 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​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The deleted rest day swap, so you have what was removed.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such rest day swap in this workspace.
429Rate limit exceeded. See the RateLimit-* headers.

List employee shifts​

GET/v1/employee_shifts

Query parameters​

NameTypeRequiredDescription
limitintegerNoPage size. Values above 100 are clamped.
starting_afterstringNoOpaque cursor from a previous response’s next_cursor.
employee_idstringNoOnly records belonging to this employee.
shift_idstringNoOnly assignments of this shift.
currentbooleanNoOnly the assignment in force today.

Responses​

StatusMeaning
200A page of employee shifts.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
429Rate 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.

Headers​

NameTypeRequiredDescription
Idempotency-KeystringNoA unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true.

Responses​

StatusMeaning
201The resulting employee shift.
400The request body failed validation.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
409The request conflicts with the current state.
429Rate limit exceeded. See the RateLimit-* headers.

Retrieve an employee shift​

GET/v1/employee_shifts/{id}

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The employee shift.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such employee shift in this workspace.
429Rate 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​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The deleted employee shift, so you have what was removed.
401The API key is missing, malformed, revoked or expired.
403The key does not carry the required scopes.
404No such employee shift in this workspace.
429Rate limit exceeded. See the RateLimit-* headers.

List attendance sites​

GET/v1/attendance_sites

Query parameters​

NameTypeRequiredDescription
limitintegerNoPage size. Values above 100 are clamped.
starting_afterstringNoOpaque cursor from a previous response’s next_cursor.
updated_sincetimestampNoReturn records changed at or after this instant. Tracks the record itself, not its child collections.
statusactive · inactiveNoOnly sites in this state.

Responses​

StatusMeaning
200A page of attendance sites.
401The API key is missing, malformed, revoked or expired.
402The workspace's plan does not include GPS attendance & field visits (plan_upgrade_required).
403The key does not carry the required scopes.
429Rate 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.

Headers​

NameTypeRequiredDescription
Idempotency-KeystringNoA unique value per logical request. Replaying it returns the original response with Idempotent-Replay: true.

Responses​

StatusMeaning
201The resulting attendance site.
400The request body failed validation.
401The API key is missing, malformed, revoked or expired.
402The workspace's plan does not include GPS attendance & field visits (plan_upgrade_required).
403The key does not carry the required scopes.
409The request conflicts with the current state.
429Rate limit exceeded. See the RateLimit-* headers.

Retrieve an attendance site​

GET/v1/attendance_sites/{id}

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The attendance site.
401The API key is missing, malformed, revoked or expired.
402The workspace's plan does not include GPS attendance & field visits (plan_upgrade_required).
403The key does not carry the required scopes.
404No such attendance site in this workspace.
429Rate 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​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The updated attendance site.
401The API key is missing, malformed, revoked or expired.
402The workspace's plan does not include GPS attendance & field visits (plan_upgrade_required).
403The key does not carry the required scopes.
404No such attendance site in this workspace.
429Rate 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​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The deleted attendance site, so you have what was removed.
401The API key is missing, malformed, revoked or expired.
402The workspace's plan does not include GPS attendance & field visits (plan_upgrade_required).
403The key does not carry the required scopes.
404No such attendance site in this workspace.
429Rate limit exceeded. See the RateLimit-* headers.

List the employees assigned to a site​

GET/v1/attendance_sites/{id}/assignments

Path parameters​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The assigned employee ids.
401The API key is missing, malformed, revoked or expired.
402The workspace's plan does not include GPS attendance & field visits (plan_upgrade_required).
403The key does not carry the required scopes.
404No such attendance site in this workspace.
429Rate 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​

NameTypeRequiredDescription
idstringYesThe identifier returned as id on the object.

Responses​

StatusMeaning
200The assigned employee ids after the change.
400One of the employees is not in this workspace.
401The API key is missing, malformed, revoked or expired.
402The workspace's plan does not include GPS attendance & field visits (plan_upgrade_required).
403The key does not carry the required scopes.
404No such attendance site in this workspace.
429Rate limit exceeded. See the RateLimit-* headers.