Endpoint Reference

Complete reference for all TempClock API v1 endpoints. All endpoints require Bearer token authentication and return JSON responses.

New in v1.1 — backwards compatible

  • GPS & geofence telemetry on /clock.php and /timesheets.php (latitude, longitude, gps_accuracy, within_geofence, distance_meters, low_gps_confidence).
  • Pre-clock-in surveys on /clock.php — supply survey_id and survey_answers, or get a 403 blocked_by_survey.
  • New /on-site-now.php endpoint — live snapshot of clocked-in workers grouped by site with geofence rollups.
  • preferred_language on workers (en, pl, ro, lt); geofence_mode, kiosk_language and gps_accuracy_threshold on locations.
  • entry_filter query param on /timesheets.php (shifts, active, breaks, all); default is shifts — matches previous behaviour.
  • Four new webhook events: clock.blocked_by_survey, clock.geofence_breach, clock.geofence_refused, clock.low_gps_confidence — opt in per subscription.

Base URL

https://tempclock.com/api/v1/
GET

/workers.php

Retrieve a paginated list of workers, or a single worker by ID. Returns worker names, contact details, locations, and status.

Required scope: workers:read

Query Parameters

Parameter Type Required Description
id integer No Return a single worker by ID. Overrides other filters.
location_id integer No Filter workers by their assigned location.
active boolean No Filter by active status. Use 1 for active, 0 for inactive.
search string No Search by first name, last name, or employee reference.
limit integer No Number of results per page. Default: 50, max: 100.
offset integer No Number of results to skip for pagination. Default: 0.

Example Request — List Workers

curl -H "Authorization: Bearer tc_live_a1b2c3..." \ "https://tempclock.com/api/v1/workers.php?active=1&location_id=3&limit=2"

Example Response

{ "data": [ { "id": 142, "first_name": "Sarah", "last_name": "Mitchell", "employee_ref": "EMP-0142", "email": "s.mitchell@example.com", "phone": "07700 900142", "location_id": 3, "location_name": "Manchester Warehouse", "department": "Picking", "active": true, "created_at": "2025-06-15T09:30:00Z" }, { "id": 156, "first_name": "James", "last_name": "Okonkwo", "employee_ref": "EMP-0156", "email": "j.okonkwo@example.com", "phone": "07700 900156", "location_id": 3, "location_name": "Manchester Warehouse", "department": "Packing", "active": true, "created_at": "2025-08-22T14:15:00Z" } ], "pagination": { "total": 34, "limit": 2, "offset": 0, "has_more": true } }

Example Request — Single Worker

curl -H "Authorization: Bearer tc_live_a1b2c3..." \ "https://tempclock.com/api/v1/workers.php?id=142"

Example Response

{ "data": { "id": 142, "first_name": "Sarah", "last_name": "Mitchell", "employee_ref": "EMP-0142", "email": "s.mitchell@example.com", "phone": "07700 900142", "location_id": 3, "location_name": "Manchester Warehouse", "department": "Picking", "active": true, "created_at": "2025-06-15T09:30:00Z" } }
GET

/timesheets.php

Retrieve a paginated list of time entries (clock-in/clock-out records). Filter by date range, worker, or location. Ideal for payroll integrations and reporting.

Required scope: timesheets:read

Query Parameters

Parameter Type Required Description
date_from string No Start date filter in YYYY-MM-DD format.
date_to string No End date filter in YYYY-MM-DD format.
worker_id integer No Filter entries for a specific worker.
location_id integer No Filter entries by location.
entry_filter
v1.1
string No One of shifts (default — completed clock-in/out shifts only), active (currently clocked-in entries within the last 14h), breaks (break entries only), or all (no filter).
limit integer No Results per page. Default: 50, max: 100.
offset integer No Number of results to skip. Default: 0.

v1.1 response fields

Time entries now also include GPS / geofence telemetry when the clock-in supplied a location: within_geofence (0 / 1 / null when geofencing is off), distance_meters, gps_accuracy, and low_gps_confidence.

Example Request

curl -H "Authorization: Bearer tc_live_a1b2c3..." \ "https://tempclock.com/api/v1/timesheets.php?date_from=2026-03-01&date_to=2026-03-07&location_id=3&entry_filter=shifts"

Example Response

{ "data": [ { "id": 8921, "worker_id": 142, "worker_name": "Sarah Mitchell", "location_id": 3, "location_name": "Manchester Warehouse", "date": "2026-03-03", "clock_in": "2026-03-03T07:02:14Z", "clock_out": "2026-03-03T15:31:47Z", "hours_worked": 8.49, "break_minutes": 30, "status": "approved", "clock_in_method": "facial_recognition", "notes": null }, { "id": 8935, "worker_id": 156, "worker_name": "James Okonkwo", "location_id": 3, "location_name": "Manchester Warehouse", "date": "2026-03-03", "clock_in": "2026-03-03T06:58:33Z", "clock_out": "2026-03-03T14:05:12Z", "hours_worked": 7.11, "break_minutes": 0, "status": "approved", "clock_in_method": "pin", "notes": "Early finish — medical appointment" } ], "pagination": { "total": 128, "limit": 50, "offset": 0, "has_more": true } }
GET

/locations.php

Retrieve a list of locations (work sites), or a single location by ID. Includes address, capacity, and active status.

Required scope: locations:read

Query Parameters

Parameter Type Required Description
id integer No Return a single location by ID.
active boolean No Filter by active status. 1 for active, 0 for inactive.
limit integer No Results per page. Default: 50, max: 100.
offset integer No Number of results to skip. Default: 0.

Example Request

curl -H "Authorization: Bearer tc_live_a1b2c3..." \ "https://tempclock.com/api/v1/locations.php?active=1"

Example Response

{ "data": [ { "id": 1, "name": "London Head Office", "address": "45 King Street, London EC2V 8DQ", "capacity": 200, "active": true, "created_at": "2024-01-10T08:00:00Z" }, { "id": 3, "name": "Manchester Warehouse", "address": "Unit 12, Trafford Park, Manchester M17 1HH", "capacity": 150, "active": true, "created_at": "2024-03-15T10:30:00Z" } ], "pagination": { "total": 5, "limit": 50, "offset": 0, "has_more": false } }
POST

/clock.php

Clock a worker in or out. This creates a real time entry in the system, identical to a kiosk clock-in. Use with care in production environments.

Required scope: clock:write

Request Body (JSON)

Field Type Required Description
worker_id integer Yes The ID of the worker to clock in or out.
action string Yes Either "in" or "out".
location_id integer No Location to clock in at. Defaults to the worker's assigned location.
notes string No Optional note attached to the time entry.
latitude
v1.1
number Conditional GPS latitude (WGS84). Required when the location is configured with geofence_mode = strict. The response will include within_geofence and distance_meters when this is supplied.
longitude
v1.1
number Conditional GPS longitude (WGS84). Paired with latitude.
gps_accuracy
v1.1
integer No Horizontal accuracy of the GPS fix in metres. Compared against the location's gps_accuracy_threshold; fixes worse than the threshold set low_gps_confidence: true in the response.
survey_id
v1.1
integer Conditional ID of the pre-clock-in survey being responded to. Required when the location has an active blocking survey, otherwise the call returns 403 blocked_by_survey.
survey_answers
v1.1
array Conditional Array of answer objects: { question_id, answer_text?, answer_bool?, answer_choice? }. Required alongside survey_id.

Example Request — Clock In

curl -X POST \ "https://tempclock.com/api/v1/clock.php" \ -H "Authorization: Bearer tc_live_a1b2c3..." \ -H "Content-Type: application/json" \ -d '{ "worker_id": 142, "action": "in", "location_id": 3, "notes": "Clocked in via API integration" }'

Example Response (201 Created)

{ "data": { "id": 9012, "worker_id": 142, "worker_name": "Sarah Mitchell", "action": "in", "location_id": 3, "location_name": "Manchester Warehouse", "timestamp": "2026-03-10T07:02:00Z", "notes": "Clocked in via API integration" }, "message": "Worker clocked in successfully." }

Error Responses

409 Conflict — Returned if the worker is already clocked in and you attempt another clock-in, or if the worker has no open clock-in and you attempt a clock-out.

{ "error": true, "message": "Worker is already clocked in.", "status": 409 }

400 Bad Request — Returned if required fields are missing or the action value is not “in” or “out”.

404 Not Found — Returned if the worker_id does not exist or belongs to another client.

403 Forbidden — blocked_by_survey (new in v1.1) — The location has a blocking pre-clock-in survey that has not been satisfied. Submit a fresh survey_id + survey_answers in a follow-up request.

{ "error": true, "error_code": "blocked_by_survey", "question_id": 34, "message": "Please see your supervisor before clocking in.", "status": 403 }

403 Forbidden — outside_geofence (new in v1.1) — The location has geofence_mode = strict and the supplied GPS coordinates were outside the radius.

{ "error": true, "error_code": "outside_geofence", "distance_meters": 412, "radius_meters": 150, "message": "You are not at Manchester Warehouse. 412m away (max 150m).", "status": 403 }
GET

/on-site-now.php

new in v1.1

Live snapshot of currently-clocked-in workers, grouped by location, with GPS / geofence rollups. Mirrors the “Site occupancy” panel on the dashboard. A worker counts as live when clock_out IS NULL and clock_in is within the last 14 hours — forgotten clock-outs are excluded so the totals match reality.

Required scope: timesheets:read

Query Parameters

Parameter Type Required Description
location_id integer No Return only the slice for a single location.
include_workers integer No Default 1. Set to 0 for an aggregate-only payload (no per-worker arrays). Use this for lightweight dashboards.

Example Request

curl -H "Authorization: Bearer tc_live_a1b2c3..." \ "https://tempclock.com/api/v1/on-site-now.php"

Example Response

{ "data": { "as_of": "2026-05-27T15:42:00Z", "totals": { "clocked_in": 12, "on_site": 11, "off_site": 1, "geofence_unknown": 0, "low_gps_confidence": 0 }, "locations": [ { "location_id": 3, "location_name": "Manchester Warehouse", "clocked_in": 5, "on_site": 5, "off_site": 0, "geofence_unknown": 0, "workers": [ { "worker_id": 142, "name": "Sarah Mitchell", "employee_id": "EMP-0142", "entry_id": 9012, "clock_in": "2026-05-27T08:01:00Z", "minutes_on_shift": 461, "within_geofence": 1, "distance_meters": 12, "gps_accuracy": 8, "low_gps_confidence": false } ] } ], "unassigned": [] } }

Note: within_geofence is null for any location where geofencing has not been configured — those workers count towards on_site and are surfaced in the geofence_unknown tally so dashboards can distinguish “inside the fence” from “no fence”.

GET POST

/shifts.php

List scheduled shifts or create new ones. GET retrieves existing shifts with filtering; POST creates a new shift assignment for a worker.

Required scopes: shifts:read (GET) shifts:write (POST)

GET Query Parameters

Parameter Type Required Description
date_from string No Start date filter (YYYY-MM-DD).
date_to string No End date filter (YYYY-MM-DD).
worker_id integer No Filter shifts for a specific worker.
location_id integer No Filter shifts by location.
limit integer No Results per page. Default: 50, max: 100.
offset integer No Number of results to skip. Default: 0.

GET Example Request

curl -H "Authorization: Bearer tc_live_a1b2c3..." \ "https://tempclock.com/api/v1/shifts.php?date_from=2026-03-10&date_to=2026-03-14&location_id=3"

GET Example Response

{ "data": [ { "id": 504, "worker_id": 142, "worker_name": "Sarah Mitchell", "location_id": 3, "location_name": "Manchester Warehouse", "shift_date": "2026-03-10", "start_time": "07:00", "end_time": "15:00", "notes": null }, { "id": 505, "worker_id": 156, "worker_name": "James Okonkwo", "location_id": 3, "location_name": "Manchester Warehouse", "shift_date": "2026-03-10", "start_time": "06:00", "end_time": "14:00", "notes": "Early start — goods delivery" } ], "pagination": { "total": 18, "limit": 50, "offset": 0, "has_more": false } }

POST Request Body (JSON)

Field Type Required Description
worker_id integer Yes The worker to assign the shift to.
shift_date string Yes Date of the shift (YYYY-MM-DD).
start_time string Yes Shift start time in HH:MM 24-hour format.
end_time string Yes Shift end time in HH:MM 24-hour format.
location_id integer No Location for the shift. Defaults to the worker's assigned location.
notes string No Optional note for the shift.

POST Example Request

curl -X POST \ "https://tempclock.com/api/v1/shifts.php" \ -H "Authorization: Bearer tc_live_a1b2c3..." \ -H "Content-Type: application/json" \ -d '{ "worker_id": 142, "shift_date": "2026-03-15", "start_time": "08:00", "end_time": "16:00", "location_id": 3, "notes": "Saturday overtime shift" }'

POST Example Response (201 Created)

{ "data": { "id": 512, "worker_id": 142, "worker_name": "Sarah Mitchell", "location_id": 3, "location_name": "Manchester Warehouse", "shift_date": "2026-03-15", "start_time": "08:00", "end_time": "16:00", "notes": "Saturday overtime shift" }, "message": "Shift created successfully." }
GET

/departments.php

Retrieve a list of departments configured for your account. Useful for mapping workers to organisational units.

Required scope: departments:read

Query Parameters

Parameter Type Required Description
active boolean No Filter by active status. 1 for active, 0 for inactive.
limit integer No Results per page. Default: 50, max: 100.
offset integer No Number of results to skip. Default: 0.

Example Request

curl -H "Authorization: Bearer tc_live_a1b2c3..." \ "https://tempclock.com/api/v1/departments.php?active=1"

Example Response

{ "data": [ { "id": 1, "name": "Picking", "active": true, "created_at": "2024-01-10T08:00:00Z" }, { "id": 2, "name": "Packing", "active": true, "created_at": "2024-01-10T08:00:00Z" }, { "id": 3, "name": "Driving", "active": true, "created_at": "2024-02-20T11:15:00Z" }, { "id": 4, "name": "Administration", "active": true, "created_at": "2024-03-01T09:00:00Z" } ], "pagination": { "total": 4, "limit": 50, "offset": 0, "has_more": false } }
GET

/cost-codes.php

Retrieve a list of cost codes used for project tracking and financial reporting. Cost codes allow you to allocate time entries to specific projects or budgets.

Required scope: cost-codes:read

Query Parameters

Parameter Type Required Description
active boolean No Filter by active status.
limit integer No Results per page. Default: 50, max: 100.
offset integer No Number of results to skip. Default: 0.

Example Request

curl -H "Authorization: Bearer tc_live_a1b2c3..." \ "https://tempclock.com/api/v1/cost-codes.php?active=1"

Example Response

{ "data": [ { "id": 1, "code": "PRJ-001", "name": "Warehouse Expansion Phase 2", "active": true, "created_at": "2025-09-01T08:00:00Z" }, { "id": 2, "code": "PRJ-002", "name": "Seasonal Q1 Campaign", "active": true, "created_at": "2026-01-05T10:30:00Z" }, { "id": 3, "code": "GEN-OPS", "name": "General Operations", "active": true, "created_at": "2024-01-10T08:00:00Z" } ], "pagination": { "total": 3, "limit": 50, "offset": 0, "has_more": false } }

Changelog

API version history and notable changes.

v1.0 Current January 2026
  • Initial public API release
  • 7 endpoints: workers, timesheets, locations, clock, shifts, departments, cost-codes
  • Bearer token authentication with scoped API keys
  • Rate limiting at 60 requests/minute per key
  • Paginated list responses with consistent format