API reference
Punches
2 endpoints. Click one to see its parameters, fields and an example. Code samples use the region you pick.
POST/v1/punchesClock in / out / break. Idempotent on local_id.
Clock in / out / break. Idempotent on local_id.
Used by the app (geofence + manual), kiosks, admins and integrations. Rejected punches are recorded as evidence and return 422 with the reason.
Body (JSON)
| Name | Type | Description |
|---|---|---|
typerequired | "in" | "out" | "break_start" | "break_end" | |
atrequired | string (date-time) | |
sourcerequired | "geofence" | "manual" | "kiosk" | "admin" | "api" | |
user_id | string | |
location_id | string | |
geofence_id | string | |
lat | number | |
lng | number | |
accuracy_m | number | |
mocked | boolean | |
low_confidence | boolean | |
local_idrequired | string | |
device_id | string | |
note | string | |
photo_asset_id | string | |
reason | string | |
project_id | string or null | |
activity_id | string or null | |
attestation | object | |
attestation.answersrequired | array of object | |
attestation.note | string | |
device_now | string (date-time) | The device's current time when sending. When it differs from the server's by more than 2 minutes, punch times are corrected by that difference (and flagged for review beyond 10 minutes). |
Example
curl -X POST "https://ca-api.clocklap.com/v1/punches" \
-H "Authorization: Bearer $CLOCKLAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type":"in","at":"2026-10-26T13:00:00Z","source":"geofence","local_id":"loc_01J…"}'Responses
200
POST/v1/punches/batchUpload queued offline punches in order. Each is applied independently.
Upload queued offline punches in order. Each is applied independently.
Body (JSON)
| Name | Type | Description |
|---|---|---|
punchesrequired | array of object | |
punches[].typerequired | "in" | "out" | "break_start" | "break_end" | |
punches[].atrequired | string (date-time) | |
punches[].sourcerequired | "geofence" | "manual" | "kiosk" | "admin" | "api" | |
punches[].user_id | string | |
punches[].location_id | string | |
punches[].geofence_id | string | |
punches[].lat | number | |
punches[].lng | number | |
punches[].accuracy_m | number | |
punches[].mocked | boolean | |
punches[].low_confidence | boolean | |
punches[].local_idrequired | string | |
punches[].device_id | string | |
punches[].note | string | |
punches[].photo_asset_id | string | |
punches[].reason | string | |
punches[].project_id | string or null | |
punches[].activity_id | string or null | |
punches[].attestation | object | |
device_now | string (date-time) | The device's current time when sending. When it differs from the server's by more than 2 minutes, punch times are corrected by that difference (and flagged for review beyond 10 minutes). |
Example
curl -X POST "https://ca-api.clocklap.com/v1/punches/batch" \
-H "Authorization: Bearer $CLOCKLAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"punches":[{"type":"in","at":"2026-10-26T13:00:00Z","source":"geofence","local_id":"loc_01J…"}],"device_now":"2026-10-26T13:00:00Z"}'Responses
200