Timesheets
Worked time. A timesheet your app creates is pending until a manager approves it in Shiftly. Pay is always worked out by Shiftly.
Needs one of the timesheets:read or timesheets:write permissions, depending on the operation. The business sees it as "Timesheets".
Fields
| Field | Type | Access | Meaning |
|---|---|---|---|
| id | string | Read-only | The timesheet. |
| employee_id | string | Writable | Who worked. |
| location_id | string | Writable | Where. |
| position_id | string | Writable | The position worked. |
| shift_id | string, may be null | Writable | The rostered shift this timesheet is for, if any. |
| start_time | timestamp | Writable | When work started. Stored to the whole minute. |
| end_time | timestamp, may be null | Writable | When work ended. Stored to the whole minute. |
| status | "pending", "approved", "rejected", "active", "posted", "warning", "skipped" | Read-only | pending until a manager approves it in Shiftly. |
| breaks | array of object | Writable | Breaks taken. |
| note | string, may be null | Writable | A note on the timesheet. |
| project_id | string, may be null | Read-only | The project the time is charged to, if any. |
| clock_in_photo_taken | boolean, may be null | Read-only | True when a photo was taken at clock-in, false when one was asked for and none was taken, null when none was asked for. The photo itself is never shared. |
| clock_out_photo_taken | boolean, may be null | Read-only | The same for clock-out. Null while the person is still clocked in. |
| paid_hours | number | Read-only | Hours paid, after unpaid breaks. Worked out by Shiftly. |
| pay | object | Read-only | What the timesheet costs, in dollars. Worked out by Shiftly. Returned only with pay:read. |
| created_by_app | boolean | Read-only | True when your app created this timesheet. |
| archived | boolean | Read-only | True when the record has been removed in Shiftly. |
| created_at | timestamp | Read-only | When the record was created. |
| updated_at | timestamp | Read-only | When the record last changed. |
Operations
List timesheets
GET/v1/timesheets
Permission: timesheets:read
| Parameter | Type | Meaning | |
|---|---|---|---|
| limit | integer, default 50, up to 200 | Optional | How many records per page. Up to 200. |
| after | string | Optional | The next_cursor from the previous page. |
| updated_since | timestamp | Optional | Only records changed at or after this moment. Pair it with include_archived to see removals. |
| include_archived | "true", "false" | Optional | Include records that have been archived. |
| from | date | Optional | The first day of the range, in the location's timezone. With to, at most 92 days. |
| to | date | Optional | The last day of the range, inclusive. |
| location_id | string | Optional | Only this location. |
| employee_id | string | Optional | Only this person. |
{
"data": [
{
"id": "66f1c2a4b3d9e8f7a6b5c4d3",
"employee_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"location_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"shift_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"status": "pending",
"breaks": [],
"note": "text",
"project_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"clock_in_photo_taken": true,
"clock_out_photo_taken": true,
"paid_hours": 1.5,
"pay": {
"total": null,
"subtotal": null,
"super": null,
"allowances": null,
"position_loading": null,
"breakdown": null
},
"created_by_app": true,
"archived": true,
"created_at": "2026-10-06T09:00:00+11:00",
"updated_at": "2026-10-06T09:00:00+11:00"
}
],
"has_more": true,
"next_cursor": "text"
}| Status | When |
|---|---|
| 400 | The error's code is invalid_request or range_too_long. The Errors page describes each code. |
| 401 | The error's code is invalid_token or token_expired. The Errors page describes each code. |
| 403 | The error's code is origin_not_allowed, permission_denied, not_available, connection_disconnected, connection_suspended or app_suspended. The Errors page describes each code. |
| 404 | There is nothing at this address, or no such record in this business. |
| 429 | Too many requests. Retry-After says when to try again. |
| 500 | Something went wrong at Shiftly. Quote the request id. |
| 503 | This environment is not set up for partner apps yet. |
Create one pending timesheet, or up to 100 in one all-or-nothing request
POST/v1/timesheets
Permission: timesheets:write
| Field | Type | Required | Meaning |
|---|---|---|---|
| employee_id | string | Required | Who worked. |
| location_id | string | Required | Where. |
| position_id | string | Required | The position worked. |
| shift_id | string | Optional | The rostered shift this timesheet is for, if any. |
| start_time | timestamp | Required | When work started. Stored to the whole minute. |
| end_time | timestamp | Required | When work ended. Stored to the whole minute. |
| breaks | array of object | Optional | Breaks taken. |
| note | string, may be null | Optional | A note on the timesheet. |
Or send { "data": [ ... ] } with up to 100 items to create several in one request. A refused batch saves nothing.
{
"employee_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"location_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"shift_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"breaks": [
{
"start": "2026-10-06T09:00:00+11:00",
"end": "2026-10-06T09:00:00+11:00",
"paid": true
}
],
"note": "text"
}{
"id": "66f1c2a4b3d9e8f7a6b5c4d3",
"employee_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"location_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"shift_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"status": "pending",
"breaks": [
{
"start": "2026-10-06T09:00:00+11:00",
"end": "2026-10-06T09:00:00+11:00",
"paid": true
}
],
"note": "text",
"project_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"clock_in_photo_taken": true,
"clock_out_photo_taken": true,
"paid_hours": 1.5,
"pay": {
"total": 1.5,
"subtotal": 1.5,
"super": 1.5,
"allowances": 1.5,
"position_loading": 1.5,
"breakdown": [
{
"category": null,
"hours": null,
"rate": null,
"cost": null
}
]
},
"created_by_app": true,
"archived": true,
"created_at": "2026-10-06T09:00:00+11:00",
"updated_at": "2026-10-06T09:00:00+11:00"
}| Status | When |
|---|---|
| 400 | The error's code is invalid_request or range_too_long. The Errors page describes each code. |
| 401 | The error's code is invalid_token or token_expired. The Errors page describes each code. |
| 403 | The error's code is origin_not_allowed, permission_denied, not_available, connection_disconnected, connection_suspended or app_suspended. The Errors page describes each code. |
| 404 | There is nothing at this address, or no such record in this business. |
| 409 | The error's code is conflict, idempotency_key_reused or request_in_progress. The Errors page describes each code. |
| 422 | A field is wrong. The field property names it. |
| 429 | Too many requests. Retry-After says when to try again. |
| 500 | Something went wrong at Shiftly. Quote the request id. |
| 503 | This environment is not set up for partner apps yet. |
Get one timesheet
GET/v1/timesheets/{id}
Permission: timesheets:read
{
"id": "66f1c2a4b3d9e8f7a6b5c4d3",
"employee_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"location_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"shift_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"status": "pending",
"breaks": [
{
"start": "2026-10-06T09:00:00+11:00",
"end": "2026-10-06T09:00:00+11:00",
"paid": true
}
],
"note": "text",
"project_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"clock_in_photo_taken": true,
"clock_out_photo_taken": true,
"paid_hours": 1.5,
"pay": {
"total": 1.5,
"subtotal": 1.5,
"super": 1.5,
"allowances": 1.5,
"position_loading": 1.5,
"breakdown": [
{
"category": null,
"hours": null,
"rate": null,
"cost": null
}
]
},
"created_by_app": true,
"archived": true,
"created_at": "2026-10-06T09:00:00+11:00",
"updated_at": "2026-10-06T09:00:00+11:00"
}| Status | When |
|---|---|
| 400 | The error's code is invalid_request or range_too_long. The Errors page describes each code. |
| 401 | The error's code is invalid_token or token_expired. The Errors page describes each code. |
| 403 | The error's code is origin_not_allowed, permission_denied, not_available, connection_disconnected, connection_suspended or app_suspended. The Errors page describes each code. |
| 404 | There is nothing at this address, or no such record in this business. |
| 429 | Too many requests. Retry-After says when to try again. |
| 500 | Something went wrong at Shiftly. Quote the request id. |
| 503 | This environment is not set up for partner apps yet. |
Correct a pending timesheet
PATCH/v1/timesheets/{id}
Permission: timesheets:write
| Field | Type | Required | Meaning |
|---|---|---|---|
| position_id | string | Optional | The position worked. |
| start_time | timestamp | Optional | When work started. Stored to the whole minute. |
| end_time | timestamp | Optional | When work ended. Stored to the whole minute. |
| breaks | array of object | Optional | Breaks taken. |
| note | string, may be null | Optional | A note on the timesheet. |
{
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"breaks": [
{
"start": "2026-10-06T09:00:00+11:00",
"end": "2026-10-06T09:00:00+11:00",
"paid": true
}
],
"note": "text"
}{
"id": "66f1c2a4b3d9e8f7a6b5c4d3",
"employee_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"location_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"shift_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"status": "pending",
"breaks": [
{
"start": "2026-10-06T09:00:00+11:00",
"end": "2026-10-06T09:00:00+11:00",
"paid": true
}
],
"note": "text",
"project_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"clock_in_photo_taken": true,
"clock_out_photo_taken": true,
"paid_hours": 1.5,
"pay": {
"total": 1.5,
"subtotal": 1.5,
"super": 1.5,
"allowances": 1.5,
"position_loading": 1.5,
"breakdown": [
{
"category": null,
"hours": null,
"rate": null,
"cost": null
}
]
},
"created_by_app": true,
"archived": true,
"created_at": "2026-10-06T09:00:00+11:00",
"updated_at": "2026-10-06T09:00:00+11:00"
}| Status | When |
|---|---|
| 400 | The error's code is invalid_request or range_too_long. The Errors page describes each code. |
| 401 | The error's code is invalid_token or token_expired. The Errors page describes each code. |
| 403 | The error's code is origin_not_allowed, permission_denied, not_available, connection_disconnected, connection_suspended or app_suspended. The Errors page describes each code. |
| 404 | There is nothing at this address, or no such record in this business. |
| 409 | The error's code is conflict, timesheet_not_pending, idempotency_key_reused or request_in_progress. The Errors page describes each code. |
| 422 | A field is wrong. The field property names it. |
| 429 | Too many requests. Retry-After says when to try again. |
| 500 | Something went wrong at Shiftly. Quote the request id. |
| 503 | This environment is not set up for partner apps yet. |
Delete a pending timesheet
DELETE/v1/timesheets/{id}
Permission: timesheets:write
{
"id": "66f1c2a4b3d9e8f7a6b5c4d3",
"deleted": true
}| Status | When |
|---|---|
| 400 | The error's code is invalid_request or range_too_long. The Errors page describes each code. |
| 401 | The error's code is invalid_token or token_expired. The Errors page describes each code. |
| 403 | The error's code is origin_not_allowed, permission_denied, not_available, connection_disconnected, connection_suspended or app_suspended. The Errors page describes each code. |
| 404 | There is nothing at this address, or no such record in this business. |
| 409 | The error's code is conflict, timesheet_not_pending, idempotency_key_reused or request_in_progress. The Errors page describes each code. |
| 422 | A field is wrong. The field property names it. |
| 429 | Too many requests. Retry-After says when to try again. |
| 500 | Something went wrong at Shiftly. Quote the request id. |
| 503 | This environment is not set up for partner apps yet. |
Not available to partner apps
POST /v1/timesheets/{id}/approve
Timesheets are approved in Shiftly, not by partner apps.
