Scheduler webhook

The Scheduler webhook sends real-time notifications whenever shifts or user availability change in your schedule. Use these webhooks to keep your systems in sync with schedule changes without polling.

Supported Events

Event TypeTriggerData Key
shift_createdA new shift is createddata.shifts
shift_updatedA shift is modified (title, time, users, status, etc.)data.shifts
shift_deletedA shift is deleteddata.ids
availability_status_createdA user submits an availability or unavailability entryavailabilityStatuses
availability_status_deletedA user's availability entry is removedavailabilityStatuses

Webhook Envelope

Every scheduler webhook payload shares the same top-level structure. Here is a complete example:

{
  "webhookVersion": 1,
  "eventType": "shift_created",
  "requestId": "b28d441c-e416-4c11-adb0-c8e0364ff29c",
  "company": "your_company_id",
  "activityType": "shift",
  "eventTimestamp": 1736760013,
  "schedulerId": 9454799,
  "data": {
    "shifts": [...]
  }
}
FieldTypeDescription
webhookVersionintegerThe webhook payload version — 1 or 2. See Shift Webhook V1 vs V2 for details.
eventTypestringThe event that triggered this webhook (e.g. shift_created, shift_updated, shift_deleted)
requestIdstringUnique identifier for this webhook delivery. Use for deduplication.
companystringYour company identifier
activityTypestring"shift" for shift events, "shift_scheduler" for availability events
eventTimestampintegerUnix timestamp of when the event occurred
schedulerIdintegerThe ID of the schedule this event belongs to
dataobjectThe event payload — structure depends on the event type (see below)
📘

Optional fields

Fields marked as optional below may be absent from the payload (not null). Design your parser to handle missing keys gracefully.


Webhook Versions: V1 & V2

Shift webhooks support two payload versions. The version you receive depends on the webhookVersion configured in your webhook subscription.

V1 (webhookVersion: 1)V2 (webhookVersion: 2)
Multi-user shiftsOne webhook call per user. A 3-user shift = 3 calls.One webhook call per shift. A 3-user shift = 1 call.
What does id represent?A user in the shiftThe shift itself
assignedUserIdsSingle user per payloadAll assigned users in one array
openSpotsPer userTotal for the shift
statusesSingle user's statusesCombined from all users
🚧

V2 webhooks are designed to work with the V2 API. Use V2 webhooks for consistent IDs and behavior with API endpoints.

📘

For detailed V1 vs V2 examples

See Shift Webhook V1 vs V2 for side-by-side payload comparisons covering multi-user shifts, open shifts, user removal, and every other scenario.


Shift Events

shift_created

Sent when one or more new shifts are created. The data.shifts array contains the full shift object(s).

{
  "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",
        "locationData": {
          "isReferencedToJob": true,
          "gps": {
            "address": "Times Square, Manhattan, NY, USA",
            "longitude": -73.9855426,
            "latitude": 40.7579747
          }
        },
        "createdBy": 9170357,
        "creationTime": 1736760011,
        "updateTime": 1736760011,
        "notes": [],
        "statuses": [],
        "breaks": [
          {
            "id": "brk-001",
            "name": "Lunch Break",
            "type": "unpaid",
            "startTime": 240,
            "duration": 30
          }
        ],
        "shiftDetails": {
          "shiftLayers": [
            {
              "id": "layer-dept",
              "title": "Department",
              "value": {
                "id": "val-kitchen",
                "displayName": "Kitchen"
              }
            }
          ]
        },
        "customFields": [
          {
            "customFieldId": 42,
            "name": "Uniform Color",
            "type": "str",
            "value": "Blue"
          }
        ]
      }
    ]
  }
}

shift_updated

Sent when a shift is modified. Same structure as shift_created but with eventType: "shift_updated". The shift objects reflect the current state after the update.

{
  "webhookVersion": 2,
  "eventType": "shift_updated",
  "requestId": "c39e552d-f527-5d22-bdc1-d9f1475gg30d",
  "company": "your_company_id",
  "activityType": "shift",
  "eventTimestamp": 1736762000,
  "schedulerId": 9454799,
  "data": {
    "shifts": [
      {
        "id": "6784dacb3c07733b0a849f49",
        "title": "Morning Shift - Updated",
        "color": "#4CAF50",
        "assignedUserIds": [9170357, 9170358],
        "startTime": 1736924400,
        "endTime": 1736946000,
        "timezone": "Asia/Jerusalem",
        "allDay": false,
        "isOpenShift": false,
        "isPublished": true,
        "updateTime": 1736762000,
        "notes": [],
        "statuses": [
          {
            "statusId": "st-001",
            "status": "accepted",
            "assignedUserId": 9170357,
            "creatingUserId": 9170357,
            "creationTime": 1736760100
          },
          {
            "statusId": "st-002",
            "status": "rejected",
            "assignedUserId": 9170358,
            "creatingUserId": 9170358,
            "creationTime": 1736760200,
            "note": "Cannot make it"
          }
        ],
        "breaks": [],
        "shiftDetails": {
          "shiftLayers": []
        },
        "customFields": []
      }
    ]
  }
}

shift_deleted

Sent when a shift is deleted. The data object contains only the IDs of deleted shifts — no full shift objects.

{
  "webhookVersion": 2,
  "eventType": "shift_deleted",
  "requestId": "5b496380-2053-414e-9a9e-983efefbb1b2",
  "company": "your_company_id",
  "activityType": "shift",
  "eventTimestamp": 1736760206,
  "schedulerId": 9454799,
  "data": {
    "ids": [
      "6784dacb3c07733b0a849f49"
    ]
  }
}
🚧

V1 vs V2 difference

In V2, ids contains one ID per shift.
In V1, ids contains one ID per user — so deleting a 3-user shift returns 3 IDs.
See Shift Webhook V1 vs V2 for details.


Shift Payload Fields

These fields appear in each shift object inside data.shifts for shift_created and shift_updated events.

FieldTypePresentDescription
idstringAlwaysUnique shift identifier
titlestringAlwaysShift name
colorstringAlwaysShift color (hex string or empty)
assignedUserIdsinteger[]AlwaysUser IDs assigned to the shift
startTimeintegerAlwaysUnix timestamp of shift start
endTimeintegerAlwaysUnix timestamp of shift end
timezonestringAlwaysIANA timezone (e.g. "America/New_York")
allDaybooleanAlwaysWhether this is an all-day shift
isOpenShiftbooleanAlwaysWhether this is an open shift (claimable by employees)
isPublishedbooleanAlwaysWhether the shift is visible to employees
isRequireAdminApprovalbooleanOptionalWhether open-shift claims require admin approval
jobIdstringOptionalAssociated job ID
locationDataobjectOptionalLocation information — see below
createdByintegerOptionalUser ID of the shift creator
creationTimeintegerOptionalUnix timestamp of creation
updateTimeintegerOptionalUnix timestamp of last update
openSpotsintegerOptionalNumber of open spots. Only present when isOpenShift is true.
notesarrayAlwaysShift notes — see below
statusesarrayAlwaysUser statuses for this shift — see below
breaksarrayAlwaysScheduled breaks — see below
shiftDetailsobjectAlwaysAdditional details including shift layers — see below
customFieldsarrayAlwaysCustom field values — see below

locationData

Location information attached to the shift.

{
  "isReferencedToJob": true,
  "gps": {
    "address": "Times Square, Manhattan, NY, USA",
    "longitude": -73.9855426,
    "latitude": 40.7579747
  }
}
FieldTypeDescription
isReferencedToJobbooleanWhether the location is inherited from the associated job
gpsobjectGPS coordinates with address (string), longitude (number), latitude (number)

statuses

Each entry represents a user's response status for the shift. In V2, this array includes statuses from all assigned users.

{
  "statusId": "abc123",
  "status": "accepted",
  "assignedUserId": 9170357,
  "creatingUserId": 9170357,
  "creationTime": 1736760013,
  "updateTime": 1736760100,
  "note": "On my way",
  "gps": {
    "address": "123 Main St",
    "longitude": -73.9855,
    "latitude": 40.7579
  }
}
FieldTypeDescription
statusIdstringUnique status record ID
statusstringOne of: accepted, rejected, checked_in, completed, claimed, claim_requested, unclaimed, unclaim_requested, cancel_claim_request, reset
assignedUserIdintegerThe user this status belongs to
creatingUserIdintegerUser who created the status
modifyingUserIdintegerUser who last modified the status (optional)
creationTimeintegerUnix timestamp of status creation (optional)
updateTimeintegerUnix timestamp of last status update (optional)
notestringStatus note text (optional)
attachmentsstring[]Attachment identifiers (optional)
gpsobjectGPS data at time of status change (optional)

breaks

Scheduled break periods within the shift.

{
  "id": "brk-001",
  "name": "Lunch Break",
  "type": "unpaid",
  "startTime": 720,
  "duration": 30
}
FieldTypeDescription
idstringUnique break ID
namestringBreak name
typestring"paid" or "unpaid"
startTimeintegerMinutes from the start of the day (e.g. 720 = 12:00 PM). Optional — may be absent for flexible breaks.
durationintegerBreak duration in minutes

notes

Shift notes attached by admins. Notes use snake_case field names (unlike the rest of the payload which uses camelCase).

Three note types exist, identified by the type field:

HTML note:

{
  "type": "html",
  "html": "<p>Remember to bring safety equipment</p>"
}

File attachment:

{
  "type": "file",
  "url": "https://files.example.com/instructions.pdf",
  "name": "instructions.pdf"
}

Image album:

{
  "type": "album",
  "album": [
    { "url": "https://files.example.com/photo1.jpg" },
    { "url": "https://files.example.com/photo2.jpg" }
  ]
}

shiftDetails

Additional metadata about the shift, primarily shift layer assignments.

{
  "shiftLayers": [
    {
      "id": "layer-dept",
      "title": "Department",
      "value": {
        "id": "val-kitchen",
        "displayName": "Kitchen"
      }
    }
  ]
}
FieldTypeDescription
shiftLayersarrayShift layer assignments. Each entry has id (layer definition ID), title (display name), and value (selected instance with id and displayName)
shiftSourcestringSource identifier for the shift (optional — only present when the shift was created from an external source)

customFields

Custom field values set on this shift. Currently supports str (text) and dropdown types.

Text custom field:

{
  "customFieldId": 42,
  "name": "Uniform Color",
  "type": "str",
  "value": "Blue"
}

Dropdown custom field:

{
  "customFieldId": 43,
  "name": "Skill Level",
  "type": "dropdown",
  "value": [
    { "id": 1, "value": "Advanced" }
  ]
}
FieldTypeDescription
customFieldIdintegerCustom field definition ID
namestringCustom field label
typestringField type — "str" or "dropdown"
valuevariesText string for str type, or array of { "id", "value" } objects for dropdown type

Availability Events

Availability webhooks notify you when users submit or remove their availability status. These events are not affected by webhook versioning — they always use the same format.

availability_status_created

{
  "eventType": "availability_status_created",
  "requestId": "2907af4d-dae5-4778-b673-d2e437701b9c",
  "company": "your_company_id",
  "activityType": "shift_scheduler",
  "eventTimestamp": 1736760518,
  "schedulerId": 9454799,
  "availabilityStatuses": [
    {
      "id": "6784dcc39585f9dc60f7a6cb",
      "type": "unavailable",
      "userId": 9170357,
      "start": {
        "timestamp": 1736935200,
        "timezone": "Asia/Jerusalem"
      },
      "end": {
        "timestamp": 1736935200,
        "timezone": "Asia/Jerusalem"
      },
      "isAllDay": true,
      "note": "Doctor appointment"
    }
  ],
  "isAdminAction": false
}

availability_status_deleted

{
  "eventType": "availability_status_deleted",
  "requestId": "bc16a835-c3c6-4a94-83bb-694cf0c138b8",
  "company": "your_company_id",
  "activityType": "shift_scheduler",
  "eventTimestamp": 1736760523,
  "schedulerId": 9454799,
  "availabilityStatuses": [
    {
      "id": "6784dcc39585f9dc60f7a6cb",
      "type": "unavailable",
      "userId": 9170357,
      "start": {
        "timestamp": 1736935200,
        "timezone": "Asia/Jerusalem"
      },
      "end": {
        "timestamp": 1736935200,
        "timezone": "Asia/Jerusalem"
      },
      "isAllDay": true,
      "note": ""
    }
  ],
  "isAdminAction": false
}

Availability Payload Fields

FieldTypeDescription
idstringUnique availability record ID
typestring"available" or "unavailable"
userIdintegerThe user this status belongs to
startobjectStart time with timestamp (Unix) and timezone (IANA)
endobjectEnd time with timestamp (Unix) and timezone (IANA)
isAllDaybooleanWhether this covers the entire day
notestringOptional note from the user
isAdminActionbooleantrue if set by an admin on behalf of the user

API Reference


What’s Next

Detailed V1 vs V2 scenarios with complete examples