Shifts
Rostered shifts. A shift your app creates is a draft until a manager publishes the roster in Shiftly. Any shift that has not started can be changed or deleted; a change to a published shift makes it a draft again until a manager republishes.
Needs one of the roster:read or roster:write permissions, depending on the operation. The business sees it as "Rosters and shifts".
Fields
| Field | Type | Access | Meaning |
|---|---|---|---|
| id | string | Read-only | The shift. |
| location_id | string | Writable | Where the shift is. |
| position_id | string | Writable | The position being worked. |
| employee_id | string, may be null | Writable | Who is rostered. Empty for an open shift. |
| roster_id | string | Read-only | The roster week Shiftly placed the shift in. |
| start_time | timestamp | Writable | When the shift starts. |
| end_time | timestamp | Writable | When the shift ends. |
| status | "unpublished", "published", "expired" | Read-only | unpublished (a draft), published or expired. Only a manager in Shiftly publishes. |
| breaks | array of object | Writable | Planned breaks. Left out on create, or when a change moves the start or end, Shiftly plans them from the award. |
| notes | string, may be null | Writable | The note on the shift, where the connecting person may see it. |
| project_id | string, may be null | Read-only | The project the shift is charged to, if any. |
| paid_hours | number, may be null | Read-only | Hours paid, after unpaid breaks. |
| cost | object | Read-only | Estimated labour cost in dollars. Zero for an open shift. Returned only with pay:read. |
| created_by_app | boolean | Read-only | True when your app created this shift. |
| 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 shifts
GET/v1/shifts
Permission: roster: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",
"location_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"employee_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"roster_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"status": "unpublished",
"breaks": [],
"notes": "text",
"project_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"paid_hours": 1.5,
"cost": {
"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 draft shift, or up to 100 in one all-or-nothing request
POST/v1/shifts
Permission: roster:write
| Field | Type | Required | Meaning |
|---|---|---|---|
| location_id | string | Required | Where the shift is. |
| position_id | string | Required | The position being worked. |
| employee_id | string, may be null | Optional | Who is rostered. Empty for an open shift. |
| start_time | timestamp | Required | When the shift starts. |
| end_time | timestamp | Required | When the shift ends. |
| breaks | array of object | Optional | Planned breaks. Left out on create, or when a change moves the start or end, Shiftly plans them from the award. |
| notes | string, may be null | Optional | The note on the shift, where the connecting person may see it. |
Or send { "data": [ ... ] } with up to 100 items to create several in one request. A refused batch saves nothing.
{
"location_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"employee_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"breaks": [
{
"offset_minutes": 1,
"duration_minutes": 1,
"paid": true
}
],
"notes": "text"
}null| 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 shift
GET/v1/shifts/{id}
Permission: roster:read
{
"id": "66f1c2a4b3d9e8f7a6b5c4d3",
"location_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"employee_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"roster_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"status": "unpublished",
"breaks": [
{
"offset_minutes": 1,
"duration_minutes": 1,
"paid": true
}
],
"notes": "text",
"project_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"paid_hours": 1.5,
"cost": {
"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. |
Change a shift that has not started
PATCH/v1/shifts/{id}
Permission: roster:write
| Field | Type | Required | Meaning |
|---|---|---|---|
| position_id | string | Optional | The position being worked. |
| employee_id | string, may be null | Optional | Who is rostered. Empty for an open shift. |
| start_time | timestamp | Optional | When the shift starts. |
| end_time | timestamp | Optional | When the shift ends. |
| breaks | array of object | Optional | Planned breaks. Left out on create, or when a change moves the start or end, Shiftly plans them from the award. |
| notes | string, may be null | Optional | The note on the shift, where the connecting person may see it. |
{
"position_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"employee_id": "66f1c2a4b3d9e8f7a6b5c4d3",
"start_time": "2026-10-06T09:00:00+11:00",
"end_time": "2026-10-06T09:00:00+11:00",
"breaks": [
{
"offset_minutes": 1,
"duration_minutes": 1,
"paid": true
}
],
"notes": "text"
}null| 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, shift_started, 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 shift that has not started
DELETE/v1/shifts/{id}
Permission: roster: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, shift_started, 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/shifts/{id}/publish
Rosters are published in Shiftly, not by partner apps.
