Shift Webhook V1 vs V2
This guide covers every scenario where V1 and V2 shift webhooks differ, with complete payload examples you can use as a reference when building your integration.
What Are V1 and V2?
Shift webhooks support two payload versions that handle multi-user shifts (shifts assigned to multiple users) differently:
- V1 (
webhookVersion: 1) — Sends a separate webhook call for each user in the shift. Theidrepresents a user in the shift. - V2 (
webhookVersion: 2) — Sends a single webhook call with all users. Theidrepresents the shift as a whole. This matches the Scheduler API format.
The version you receive depends on the webhookVersion configured in your webhook subscription.
ImportantV2 webhooks are designed to work with the V2 API. If you are using V2 API endpoints, use V2 webhooks for consistent IDs and behavior.
Quick Comparison
| Aspect | V1 | V2 |
|---|---|---|
| Webhook calls per multi-user shift (3 users) | 3 calls | 1 call |
What does the id represent? | A user in the shift | The shift itself |
assignedUserIds per payload | 1 user | All users |
openSpots | Per user | Total for the shift |
statuses | Single user's statuses | All users' statuses combined |
| Adding a user to a shift | shift_created (new user) | shift_updated (updated shift) |
Scenarios
1. Creating a Single-User Shift
When a shift is assigned to one user, V1 and V2 are nearly identical — both send a single webhook call.
V2 payload:
{
"webhookVersion": 2,
"eventType": "shift_created",
"requestId": "b28d441c-e416-4c11-adb0-c8e0364ff29c",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736760013,
"schedulerId": 9454799,
"data": {
"shifts": [
{
"id": "6784dacb3c07733b0a849f49",
"title": "Morning Shift",
"color": "#4CAF50",
"assignedUserIds": [9170357],
"startTime": 1736924400,
"endTime": 1736942400,
"timezone": "Asia/Jerusalem",
"allDay": false,
"isOpenShift": false,
"isPublished": true,
"isRequireAdminApproval": false,
"jobId": "d4ad7232-576f-2ff6-c57d-8240f1089b00",
"createdBy": 9170357,
"creationTime": 1736760011,
"updateTime": 1736760011,
"notes": [],
"statuses": [],
"breaks": [],
"shiftDetails": { "shiftLayers": [] },
"customFields": []
}
]
}
}V1 payload — same structure, but webhookVersion: 1 and a different id:
{
"webhookVersion": 1,
"eventType": "shift_created",
"...": "...same envelope fields...",
"data": {
"shifts": [
{
"id": "8a23dacb3c07733b0a849abc",
"title": "Morning Shift",
"assignedUserIds": [9170357],
"...": "...same shift fields..."
}
]
}
}2. Creating a Multi-User Shift
This is the most important difference between V1 and V2.
Scenario: An admin creates "Morning Shift" and assigns it to 3 users: 9170357, 9170358, and 9170359.
V2: 1 Webhook Call
All 3 users appear in a single payload:
{
"webhookVersion": 2,
"eventType": "shift_created",
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736760013,
"schedulerId": 9454799,
"data": {
"shifts": [
{
"id": "6784dacb3c07733b0a849f49",
"title": "Morning Shift",
"color": "#4CAF50",
"assignedUserIds": [9170357, 9170358, 9170359],
"startTime": 1736924400,
"endTime": 1736942400,
"timezone": "Asia/Jerusalem",
"allDay": false,
"isOpenShift": false,
"isPublished": true,
"statuses": [],
"breaks": [],
"shiftDetails": { "shiftLayers": [] },
"customFields": []
}
]
}
}V1: 3 Separate Webhook Calls
Each user gets their own webhook call with a unique id:
Call 1 of 3 — User 9170357:
{
"webhookVersion": 1,
"eventType": "shift_created",
"requestId": "a1b2c3d4-0001",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736760013,
"schedulerId": 9454799,
"data": {
"shifts": [
{
"id": "8a23dacb3c07733b0a849abc",
"title": "Morning Shift",
"assignedUserIds": [9170357],
"startTime": 1736924400,
"endTime": 1736942400,
"timezone": "Asia/Jerusalem",
"allDay": false,
"isOpenShift": false,
"isPublished": true,
"statuses": [],
"breaks": [],
"shiftDetails": { "shiftLayers": [] },
"customFields": []
}
]
}
}Call 2 of 3 — User 9170358:
{
"webhookVersion": 1,
"eventType": "shift_created",
"requestId": "a1b2c3d4-0002",
"...": "...same envelope...",
"data": {
"shifts": [
{
"id": "9b34eadc4d08844c1b950bcd",
"title": "Morning Shift",
"assignedUserIds": [9170358],
"...": "...same shift fields..."
}
]
}
}Call 3 of 3 — User 9170359:
{
"webhookVersion": 1,
"eventType": "shift_created",
"requestId": "a1b2c3d4-0003",
"...": "...same envelope...",
"data": {
"shifts": [
{
"id": "ac45fbfd5e19955d2ca61cde",
"title": "Morning Shift",
"assignedUserIds": [9170359],
"...": "...same shift fields..."
}
]
}
}3. Creating an Open Shift
Open shifts allow employees to claim available spots.
V2 payload:
{
"webhookVersion": 2,
"eventType": "shift_created",
"requestId": "open-shift-001",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736760013,
"schedulerId": 9454799,
"data": {
"shifts": [
{
"id": "7894dacb3c07733b0a849f50",
"title": "Open Morning Shift",
"color": "#FF9800",
"assignedUserIds": [],
"startTime": 1736924400,
"endTime": 1736942400,
"timezone": "Asia/Jerusalem",
"allDay": false,
"isOpenShift": true,
"isPublished": true,
"isRequireAdminApproval": false,
"openSpots": 5,
"statuses": [],
"breaks": [],
"shiftDetails": { "shiftLayers": [] },
"customFields": []
}
]
}
}In V2, openSpots represents the total available spots for the shift. As employees claim spots, assignedUserIds grows and openSpots decreases.
4. Updating a Shift
When a shift is updated (title, time, status change, etc.), both V1 and V2 send shift_updated. The payload contains the current state of the shift after the update.
V2 payload:
{
"webhookVersion": 2,
"eventType": "shift_updated",
"requestId": "update-001",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736762000,
"schedulerId": 9454799,
"data": {
"shifts": [
{
"id": "6784dacb3c07733b0a849f49",
"title": "Morning Shift - Updated",
"color": "#4CAF50",
"assignedUserIds": [9170357, 9170358, 9170359],
"startTime": 1736924400,
"endTime": 1736946000,
"timezone": "Asia/Jerusalem",
"allDay": false,
"isOpenShift": false,
"isPublished": true,
"updateTime": 1736762000,
"statuses": [
{
"statusId": "st-001",
"status": "accepted",
"assignedUserId": 9170357,
"creatingUserId": 9170357,
"creationTime": 1736760100
},
{
"statusId": "st-002",
"status": "rejected",
"assignedUserId": 9170358,
"creatingUserId": 9170358,
"creationTime": 1736760200
}
],
"breaks": [],
"shiftDetails": { "shiftLayers": [] },
"customFields": []
}
]
}
}Key V2 details for multi-user shifts:
assignedUserIds— all current users in the shiftstatuses— combined from all users (use theassignedUserIdfield on each status to identify which user it belongs to)updateTime— the most recent update across all users
5. Deleting a Shift
When a shift is deleted, the payload contains only the IDs — no full shift objects.
V2 payload:
{
"webhookVersion": 2,
"eventType": "shift_deleted",
"requestId": "delete-001",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736763000,
"schedulerId": 9454799,
"data": {
"ids": ["6784dacb3c07733b0a849f49"]
}
}V2 returns 1 shift ID regardless of how many users were assigned.
V1 payload:
{
"webhookVersion": 1,
"eventType": "shift_deleted",
"requestId": "delete-001",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736763000,
"schedulerId": 9454799,
"data": {
"ids": [
"8a23dacb3c07733b0a849abc",
"9b34eadc4d08844c1b950bcd",
"ac45fbfd5e19955d2ca61cde"
]
}
}V1 returns one ID per user in the shift. A 3-user shift deletion produces 3 IDs.
6. Removing a User from a Multi-User Shift
When a user is removed from a shift but other users remain, the system sends two separate webhooks.
Scenario: A shift has 3 users (9170357, 9170358, 9170359). An admin removes user 9170359.
Webhook 1 — shift_updated
shift_updatedShows the shift with the updated user list:
{
"webhookVersion": 2,
"eventType": "shift_updated",
"requestId": "partial-delete-001",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736763000,
"schedulerId": 9454799,
"data": {
"shifts": [
{
"id": "6784dacb3c07733b0a849f49",
"title": "Morning Shift",
"assignedUserIds": [9170357, 9170358],
"startTime": 1736924400,
"endTime": 1736942400,
"timezone": "Asia/Jerusalem",
"allDay": false,
"isOpenShift": false,
"isPublished": true,
"statuses": [],
"breaks": [],
"shiftDetails": { "shiftLayers": [] },
"customFields": []
}
]
}
}Notice assignedUserIds now has 2 users instead of 3.
Webhook 2 — shift_deleted
shift_deletedReports the removal. The content differs by version:
V2:
{
"webhookVersion": 2,
"eventType": "shift_deleted",
"requestId": "partial-delete-002",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736763000,
"schedulerId": 9454799,
"data": {
"ids": []
}
}
Why isidsempty in V2?In V2, the shift still exists (with 2 remaining users), so no shift ID is deleted. V2 only includes an ID in
shift_deletedwhen the entire shift is removed. For partial user removals, theshift_updatedwebhook above is the primary notification.
V1:
{
"webhookVersion": 1,
"eventType": "shift_deleted",
"requestId": "partial-delete-002",
"...": "...same envelope...",
"data": {
"ids": [
"ac45fbfd5e19955d2ca61cde"
]
}
}V1 includes the ID for the removed user.
ImportantThis dual-webhook pattern (
shift_updated+shift_deleted) only happens when some users remain on the shift. If you delete the entire shift (all users), onlyshift_deletedfires.
7. Adding a User to an Existing Shift
When a new user is added to a shift, V1 and V2 send different event types.
Scenario: A shift has 2 users (9170357, 9170358). User 9170360 is added.
V2: shift_updated
shift_updatedV2 treats this as an update to the existing shift:
{
"webhookVersion": 2,
"eventType": "shift_updated",
"requestId": "add-user-001",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736764000,
"schedulerId": 9454799,
"data": {
"shifts": [
{
"id": "6784dacb3c07733b0a849f49",
"title": "Morning Shift",
"assignedUserIds": [9170357, 9170358, 9170360],
"startTime": 1736924400,
"endTime": 1736942400,
"timezone": "Asia/Jerusalem",
"allDay": false,
"isOpenShift": false,
"isPublished": true,
"statuses": [],
"breaks": [],
"shiftDetails": { "shiftLayers": [] },
"customFields": []
}
]
}
}V1: shift_created
shift_createdV1 treats adding a user as a new entry and sends shift_created for the added user only:
{
"webhookVersion": 1,
"eventType": "shift_created",
"requestId": "add-user-001",
"company": "your_company_id",
"activityType": "shift",
"eventTimestamp": 1736764000,
"schedulerId": 9454799,
"data": {
"shifts": [
{
"id": "bd56gcge6f2aa66e3db72def",
"title": "Morning Shift",
"assignedUserIds": [9170360],
"startTime": 1736924400,
"endTime": 1736942400,
"timezone": "Asia/Jerusalem",
"allDay": false,
"isOpenShift": false,
"isPublished": true,
"statuses": [],
"breaks": [],
"shiftDetails": { "shiftLayers": [] },
"customFields": []
}
]
}
}
V1 does not notify about existing usersWhen a user is added, V1 only sends
shift_createdfor the new user. Existing users are not included.
Migration Checklist
If you are upgrading from V1 to V2 webhooks:
- Handle multiple users per payload — V2 payloads can include multiple users in
assignedUserIds. Update any code that assumes 1 user per webhook. - Expect fewer webhook calls — A shift with N users triggers 1 V2 call instead of N V1 calls.
- Use the shift ID directly — V2 returns the same ID format as the Scheduler API.
- Handle the update+delete pattern — When a user is removed from a shift, you receive both
shift_updated(remaining users) andshift_deleted. The V2shift_deletedmay have emptyidsfor partial removals. - Check for aggregated
openSpots— V2 reports the total open spots for the shift. - Parse combined
statuses— V2 includes statuses from all users. Use theassignedUserIdfield on each status to identify the user. - Adding user =
shift_updated— In V2, adding a user triggersshift_updated(notshift_created). Update your event routing logic accordingly.
Updated about 5 hours ago
