Get Timesheet
Aggregated actual hours per staff member for a date range — ready for payroll. Dates are interpreted in the supplier's timezone.
Endpoint
GET /v1/staff/timesheet
Authentication
Requires an API key with the staff:read scope.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Range start date (YYYY-MM-DD, supplier timezone) |
to | string | Yes | Range end date (YYYY-MM-DD, inclusive) |
staff_id | integer | No | Limit to one staff member |
Response
Success (200 OK)
{
"data": {
"from": "2026-06-08",
"to": "2026-06-14",
"total_worked_minutes": 2310,
"staff": [
{
"staff_id": 5,
"first_name": "Jane",
"last_name": "Smith",
"worked_minutes": 1380,
"break_minutes": 90,
"entries": [
{
"id": 12,
"clock_in_at": "2026-06-12T22:58:00+00:00",
"clock_out_at": "2026-06-13T07:04:00+00:00",
"break_minutes": 30,
"worked_minutes": 456,
"source": "kiosk"
}
]
}
],
"payroll": {
"label": "Jun 8 - Jun 21",
"unmatched": [
{ "id": 9, "name": "Sam Lee" }
],
"changed": [
{ "name": "Jane Smith", "label": "May 25 - Jun 7" }
],
"failed": [],
"run_error": null
}
},
"meta": { "request_id": "req_abc123", "timestamp": "2026-06-13T10:00:00+00:00" }
}
Payroll
payroll is null when the business does not send hours to Xero Payroll. Otherwise it says where the hours stand there. It reads EquipDash's own records and does not call Xero.
| Field | Type | Description |
|---|---|---|
label | string|null | The open pay period the hours are going to, for example "Jun 8 - Jun 21". null before hours have been sent for the first time, or once that period has ended |
unmatched | array | Staff with hours in the open pay period who are not matched to an employee in Xero, so their hours are not sent. Each has id (the staff id) and name |
changed | array | Staff whose hours changed after Xero approved or processed that pay period, so Xero still has the old hours. Each has name and label (the pay period) |
failed | array | Staff whose hours did not reach Xero. Each has name and error, the reason |
run_error | string|null | Why the last send stopped before it reached anyone, for example Xero Payroll not being set up in the Xero organization. null when the last send ran |
To send the hours now instead of waiting for the nightly send, use Send Hours to Payroll.
Errors
| Status | Code | Description |
|---|---|---|
| 422 | validation_failed | Missing/invalid from/to, or cross-supplier staff_id |
| 403 | insufficient_scope | API key lacks staff:read scope |
Example Request
curl "https://app.equipdash.com/api/v1/staff/timesheet?from=2026-06-08&to=2026-06-14" \
-H "Authorization: Bearer YOUR_API_KEY"