Code Examples

Ready-to-use code for common operations in cURL, PHP, Python, and Node.js. All examples include error handling and use environment variables for API keys.

Before you start: All examples assume your API key is stored in an environment variable called TEMPCLOCK_API_KEY. Set it with:
export TEMPCLOCK_API_KEY="tc_live_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"

List All Active Workers

Fetch all active workers with pagination support. Uses GET /workers.php.

curl -X GET \ "https://tempclock.com/api/v1/workers.php?active=1&limit=50&offset=0" \ -H "Authorization: Bearer $TEMPCLOCK_API_KEY" \ -H "Content-Type: application/json"
<?php $api_key = getenv('TEMPCLOCK_API_KEY'); $base_url = 'https://tempclock.com/api/v1'; $params = [ 'active' => 1, 'limit' => 50, 'offset' => 0, ]; $url = $base_url . '/workers.php?' . http_build_query($params); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $api_key, 'Content-Type: application/json', ], ]); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $data = json_decode($response, true); if ($status !== 200) { echo "Error {$status}: " . $data['message'] . "\n"; exit(1); } foreach ($data['data'] as $worker) { printf("[%d] %s %s — %s\n", $worker['id'], $worker['first_name'], $worker['last_name'], $worker['location_name'] ); } echo "Total: " . $data['pagination']['total'] . " workers\n";
import os import requests API_KEY = os.environ["TEMPCLOCK_API_KEY"] BASE_URL = "https://tempclock.com/api/v1" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } params = { "active": 1, "limit": 50, "offset": 0, } response = requests.get( f"{BASE_URL}/workers.php", headers=headers, params=params, ) if response.status_code != 200: error = response.json() print(f"Error {error['status']}: {error['message']}") exit(1) data = response.json() for worker in data["data"]: print(f"[{worker['id']}] {worker['first_name']} {worker['last_name']} — {worker['location_name']}") print(f"\nTotal: {data['pagination']['total']} workers")
const API_KEY = process.env.TEMPCLOCK_API_KEY; const BASE_URL = "https://tempclock.com/api/v1"; async function listActiveWorkers() { const params = new URLSearchParams({ active: "1", limit: "50", offset: "0", }); const response = await fetch( `${BASE_URL}/workers.php?${params}`, { headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json", }, } ); const data = await response.json(); if (!response.ok) { console.error(`Error ${data.status}: ${data.message}`); process.exit(1); } data.data.forEach(worker => { console.log(`[${worker.id}] ${worker.first_name} ${worker.last_name} — ${worker.location_name}`); }); console.log(`\nTotal: ${data.pagination.total} workers`); } listActiveWorkers();

Get Timesheets for a Date Range

Pull timesheet data for a specific week, handling pagination to fetch all results. Uses GET /timesheets.php.

# Fetch timesheets for the first week of March 2026 curl -X GET \ "https://tempclock.com/api/v1/timesheets.php?date_from=2026-03-01&date_to=2026-03-07&limit=100" \ -H "Authorization: Bearer $TEMPCLOCK_API_KEY"
<?php $api_key = getenv('TEMPCLOCK_API_KEY'); $base_url = 'https://tempclock.com/api/v1'; // Fetch all timesheets for a date range, handling pagination function getAllTimesheets(string $from, string $to): array { global $api_key, $base_url; $all_entries = []; $offset = 0; $limit = 100; do { $url = $base_url . '/timesheets.php?' . http_build_query([ 'date_from' => $from, 'date_to' => $to, 'limit' => $limit, 'offset' => $offset, ]); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $api_key], ]); $result = json_decode(curl_exec($ch), true); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status !== 200) { throw new Exception("API error: " . $result['message']); } $all_entries = array_merge($all_entries, $result['data']); $offset += $limit; } while ($result['pagination']['has_more']); return $all_entries; } $entries = getAllTimesheets('2026-03-01', '2026-03-07'); echo "Fetched " . count($entries) . " timesheet entries\n";
import os import requests API_KEY = os.environ["TEMPCLOCK_API_KEY"] BASE_URL = "https://tempclock.com/api/v1" HEADERS = {"Authorization": f"Bearer {API_KEY}"} def get_all_timesheets(date_from: str, date_to: str) -> list: """Fetch all timesheets for a date range, handling pagination.""" all_entries = [] offset = 0 limit = 100 while True: resp = requests.get( f"{BASE_URL}/timesheets.php", headers=HEADERS, params={ "date_from": date_from, "date_to": date_to, "limit": limit, "offset": offset, }, ) resp.raise_for_status() data = resp.json() all_entries.extend(data["data"]) if not data["pagination"]["has_more"]: break offset += limit return all_entries entries = get_all_timesheets("2026-03-01", "2026-03-07") print(f"Fetched {len(entries)} timesheet entries") for entry in entries: print(f" {entry['date']} | {entry['worker_name']} | {entry['hours_worked']}h")
const API_KEY = process.env.TEMPCLOCK_API_KEY; const BASE_URL = "https://tempclock.com/api/v1"; async function getAllTimesheets(dateFrom, dateTo) { const allEntries = []; let offset = 0; const limit = 100; while (true) { const params = new URLSearchParams({ date_from: dateFrom, date_to: dateTo, limit: String(limit), offset: String(offset), }); const resp = await fetch(`${BASE_URL}/timesheets.php?${params}`, { headers: { "Authorization": `Bearer ${API_KEY}` }, }); if (!resp.ok) { const err = await resp.json(); throw new Error(`API Error ${err.status}: ${err.message}`); } const data = await resp.json(); allEntries.push(...data.data); if (!data.pagination.has_more) break; offset += limit; } return allEntries; } (async () => { const entries = await getAllTimesheets("2026-03-01", "2026-03-07"); console.log(`Fetched ${entries.length} entries`); entries.forEach(e => console.log(` ${e.date} | ${e.worker_name} | ${e.hours_worked}h`)); })();

Clock In a Worker

Clock a worker in at a specific location, with error handling for the 409 conflict case. Uses POST /clock.php.

curl -X POST \ "https://tempclock.com/api/v1/clock.php" \ -H "Authorization: Bearer $TEMPCLOCK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "worker_id": 142, "action": "in", "location_id": 3, "notes": "Clocked in via API" }'
<?php $api_key = getenv('TEMPCLOCK_API_KEY'); $base_url = 'https://tempclock.com/api/v1'; $payload = json_encode([ 'worker_id' => 142, 'action' => 'in', 'location_id' => 3, 'notes' => 'Clocked in via API', ]); $ch = curl_init($base_url . '/clock.php'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $api_key, 'Content-Type: application/json', ], ]); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $data = json_decode($response, true); if ($status === 201) { echo "Success: " . $data['message'] . "\n"; echo "Entry ID: " . $data['data']['id'] . "\n"; } elseif ($status === 409) { echo "Conflict: " . $data['message'] . "\n"; // Worker is already clocked in — handle gracefully } else { echo "Error {$status}: " . $data['message'] . "\n"; }
import os import requests API_KEY = os.environ["TEMPCLOCK_API_KEY"] BASE_URL = "https://tempclock.com/api/v1" payload = { "worker_id": 142, "action": "in", "location_id": 3, "notes": "Clocked in via API", } response = requests.post( f"{BASE_URL}/clock.php", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json=payload, ) data = response.json() if response.status_code == 201: print(f"Success: {data['message']}") print(f"Entry ID: {data['data']['id']}") elif response.status_code == 409: print(f"Conflict: {data['message']}") # Worker already clocked in — handle gracefully else: print(f"Error {data['status']}: {data['message']}")
const API_KEY = process.env.TEMPCLOCK_API_KEY; const BASE_URL = "https://tempclock.com/api/v1"; async function clockInWorker(workerId, locationId, notes) { const response = await fetch(`${BASE_URL}/clock.php`, { method: "POST", headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ worker_id: workerId, action: "in", location_id: locationId, notes, }), }); const data = await response.json(); if (response.status === 201) { console.log(`Success: ${data.message}`); console.log(`Entry ID: ${data.data.id}`); return data.data; } else if (response.status === 409) { console.warn(`Conflict: ${data.message}`); // Worker already clocked in — handle gracefully return null; } else { throw new Error(`Error ${data.status}: ${data.message}`); } } clockInWorker(142, 3, "Clocked in via API");

Create a Shift

Schedule a new shift for a worker. Uses POST /shifts.php.

curl -X POST \ "https://tempclock.com/api/v1/shifts.php" \ -H "Authorization: Bearer $TEMPCLOCK_API_KEY" \ -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" }'
<?php $api_key = getenv('TEMPCLOCK_API_KEY'); $base_url = 'https://tempclock.com/api/v1'; $shift = json_encode([ 'worker_id' => 142, 'shift_date' => '2026-03-15', 'start_time' => '08:00', 'end_time' => '16:00', 'location_id' => 3, 'notes' => 'Saturday overtime', ]); $ch = curl_init($base_url . '/shifts.php'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $shift, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $api_key, 'Content-Type: application/json', ], ]); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $data = json_decode($response, true); if ($status === 201) { echo "Shift created: " . $data['message'] . "\n"; echo "Shift ID: " . $data['data']['id'] . "\n"; } else { echo "Error {$status}: " . $data['message'] . "\n"; }
import os import requests API_KEY = os.environ["TEMPCLOCK_API_KEY"] BASE_URL = "https://tempclock.com/api/v1" shift_data = { "worker_id": 142, "shift_date": "2026-03-15", "start_time": "08:00", "end_time": "16:00", "location_id": 3, "notes": "Saturday overtime", } response = requests.post( f"{BASE_URL}/shifts.php", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json=shift_data, ) data = response.json() if response.status_code == 201: print(f"Shift created: {data['message']}") print(f"Shift ID: {data['data']['id']}") print(f" Worker: {data['data']['worker_name']}") print(f" Date: {data['data']['shift_date']}") print(f" Time: {data['data']['start_time']} — {data['data']['end_time']}") else: print(f"Error {data['status']}: {data['message']}")
const API_KEY = process.env.TEMPCLOCK_API_KEY; const BASE_URL = "https://tempclock.com/api/v1"; async function createShift(shiftData) { const response = await fetch(`${BASE_URL}/shifts.php`, { method: "POST", headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify(shiftData), }); const data = await response.json(); if (response.status === 201) { console.log(`Shift created: ${data.message}`); console.log(` ID: ${data.data.id}`); console.log(` Worker: ${data.data.worker_name}`); console.log(` Date: ${data.data.shift_date}`); console.log(` Time: ${data.data.start_time} — ${data.data.end_time}`); return data.data; } else { throw new Error(`Error ${data.status}: ${data.message}`); } } createShift({ worker_id: 142, shift_date: "2026-03-15", start_time: "08:00", end_time: "16:00", location_id: 3, notes: "Saturday overtime", });

Clock In with GPS & Pre-Clock Survey

v1.1

Submit GPS coordinates and the worker's pre-clock-in survey answers in a single POST /clock.php. Handles the three v1.1 refusal cases: blocked_by_survey, outside_geofence, and standard 409 "already clocked in".

curl -X POST \ "https://tempclock.com/api/v1/clock.php" \ -H "Authorization: Bearer $TEMPCLOCK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "worker_id": 142, "action": "in", "location_id": 3, "latitude": 53.4839, "longitude": -2.2446, "gps_accuracy": 8, "survey_id": 7, "survey_answers": [ { "question_id": 33, "answer_value": "no" }, { "question_id": 34, "answer_value": "yes" } ] }'
<?php $api_key = getenv('TEMPCLOCK_API_KEY'); $body = [ 'worker_id' => 142, 'action' => 'in', 'location_id' => 3, 'latitude' => 53.4839, 'longitude' => -2.2446, 'gps_accuracy'=> 8, 'survey_id' => 7, 'survey_answers'=> [ ['question_id' => 33, 'answer_value' => 'no'], ['question_id' => 34, 'answer_value' => 'yes'], ], ]; $ch = curl_init('https://tempclock.com/api/v1/clock.php'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($body), CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $api_key, 'Content-Type: application/json', ], ]); $resp = json_decode(curl_exec($ch), true); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status === 201) { $d = $resp['data']; echo "Clocked in #{$d['entry_id']}"; if (!empty($d['low_gps_confidence'])) { echo ' (GPS was fuzzy)'; } } elseif ($status === 403 && ($resp['error_code'] ?? '') === 'blocked_by_survey') { // Worker needs to retake the survey before clocking in. echo "Blocked by survey question #{$resp['question_id']}: {$resp['message']}"; } elseif ($status === 403 && ($resp['error_code'] ?? '') === 'outside_geofence') { echo "Off-site: {$resp['distance_meters']}m away (allowed {$resp['radius_meters']}m)"; } else { echo "Error: {$resp['message']}"; }
import os, requests api_key = os.environ["TEMPCLOCK_API_KEY"] payload = { "worker_id": 142, "action": "in", "location_id": 3, "latitude": 53.4839, "longitude": -2.2446, "gps_accuracy": 8, "survey_id": 7, "survey_answers": [ {"question_id": 33, "answer_value": "no"}, {"question_id": 34, "answer_value": "yes"}, ], } r = requests.post( "https://tempclock.com/api/v1/clock.php", json=payload, headers={"Authorization": f"Bearer {api_key}"}, timeout=10, ) body = r.json() if r.status_code == 201: d = body["data"] print(f"Clocked in #{d['entry_id']}", "(off-site)" if d.get("within_geofence") == 0 else "") elif body.get("error_code") == "blocked_by_survey": print("Survey block:", body["message"]) elif body.get("error_code") == "outside_geofence": print(f"Off-site: {body['distance_meters']}m") else: print("Error:", body["message"])

Build a "who's on site" widget

v1.1

Poll GET /on-site-now.php every minute to mirror the dashboard's live occupancy panel inside your own CRM. The endpoint already excludes forgotten clock-outs (anything older than 14 hours) so you don't have to clean up.

curl -H "Authorization: Bearer $TEMPCLOCK_API_KEY" \ "https://tempclock.com/api/v1/on-site-now.php?include_workers=0"
import os, requests, time api_key = os.environ["TEMPCLOCK_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} while True: r = requests.get( "https://tempclock.com/api/v1/on-site-now.php", headers=headers, timeout=10, ) snap = r.json()["data"] t = snap["totals"] print(f"As of {snap['as_of']} — " f"{t['clocked_in']} clocked in " f"({t['on_site']} on-site, {t['off_site']} off-site, " f"{t['low_gps_confidence']} low-GPS)") for loc in snap["locations"]: print(f" {loc['location_name']}: {loc['clocked_in']} clocked in") time.sleep(60)
async function tick() { const r = await fetch( "https://tempclock.com/api/v1/on-site-now.php", { headers: { "Authorization": `Bearer ${process.env.TEMPCLOCK_API_KEY}` } }, ); const { data } = await r.json(); console.log(`${data.totals.clocked_in} on shift — ${data.totals.off_site} off-site`); data.locations.forEach(l => console.log(` ${l.location_name}: ${l.clocked_in}`)); } setInterval(tick, 60_000); tick();