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. The id represents a user in the shift.
  • V2 (webhookVersion: 2) — Sends a single webhook call with all users. The id represents the shift as a whole. This matches the Scheduler API format.

The version you receive depends on the webhookVersion configured in your webhook subscription.

🚧

Important

V2 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

AspectV1V2
Webhook calls per multi-user shift (3 users)3 calls1 call
What does the id represent?A user in the shiftThe shift itself
assignedUserIds per payload1 userAll users
openSpotsPer userTotal for the shift
statusesSingle user's statusesAll users' statuses combined
Adding a user to a shiftshift_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 shift
  • statuses — combined from all users (use the assignedUserId field 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

Shows 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

Reports 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 is ids empty 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_deleted when the entire shift is removed. For partial user removals, the shift_updated webhook 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.

🚧

Important

This dual-webhook pattern (shift_updated + shift_deleted) only happens when some users remain on the shift. If you delete the entire shift (all users), only shift_deleted fires.


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

V2 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

V1 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 users

When a user is added, V1 only sends shift_created for 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) and shift_deleted. The V2 shift_deleted may have empty ids for 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 the assignedUserId field on each status to identify the user.
  • Adding user = shift_updated — In V2, adding a user triggers shift_updated (not shift_created). Update your event routing logic accordingly.

← Scheduler Webhook

API Reference