---
updatedAt: 2026-04-14T10:02:39.000Z
---

Fetch the complete documentation index at: https://developer.connecteam.com/llms.txt. Use this file to discover all available pages before exploring further.

# 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 Type                    | Trigger                                                | Data Key               |
| :---------------------------- | :----------------------------------------------------- | :--------------------- |
| `shift_created`               | A new shift is created                                 | `data.shifts`          |
| `shift_updated`               | A shift is modified (title, time, users, status, etc.) | `data.shifts`          |
| `shift_deleted`               | A shift is deleted                                     | `data.ids`             |
| `availability_status_created` | A user submits an availability or unavailability entry | `availabilityStatuses` |
| `availability_status_deleted` | A user's availability entry is removed                 | `availabilityStatuses` |

***

## Webhook Envelope

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

```json
{
  "webhookVersion": 1,
  "eventType": "shift_created",
  "requestId": "b28d441c-e416-4c11-adb0-c8e0364ff29c",
  "company": "your_company_id",
  "activityType": "shift",
  "eventTimestamp": 1736760013,
  "schedulerId": 9454799,
  "data": {
    "shifts": [...]
  }
}
```

| Field            | Type    | Description                                                                                                 |
| :--------------- | :------ | :---------------------------------------------------------------------------------------------------------- |
| `webhookVersion` | integer | The webhook payload version — `1` or `2`. See [Shift Webhook V1 vs V2](shift-webhook-v1-vs-v2) for details. |
| `eventType`      | string  | The event that triggered this webhook (e.g. `shift_created`, `shift_updated`, `shift_deleted`)              |
| `requestId`      | string  | Unique identifier for this webhook delivery. Use for deduplication.                                         |
| `company`        | string  | Your company identifier                                                                                     |
| `activityType`   | string  | `"shift"` for shift events, `"shift_scheduler"` for availability events                                     |
| `eventTimestamp` | integer | Unix timestamp of when the event occurred                                                                   |
| `schedulerId`    | integer | The ID of the schedule this event belongs to                                                                |
| `data`           | object  | The 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 shifts**         | One 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 shift                                  | The shift itself                                     |
| **`assignedUserIds`**         | Single user per payload                              | All assigned users in one array                      |
| **`openSpots`**               | Per user                                             | Total for the shift                                  |
| **`statuses`**                | Single user's statuses                               | Combined 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](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).

```json
{
  "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.

```json
{
  "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.

```json
{
  "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](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.

| Field                    | Type       | Present  | Description                                                      |
| :----------------------- | :--------- | :------- | :--------------------------------------------------------------- |
| `id`                     | string     | Always   | Unique shift identifier                                          |
| `title`                  | string     | Always   | Shift name                                                       |
| `color`                  | string     | Always   | Shift color (hex string or empty)                                |
| `assignedUserIds`        | integer\[] | Always   | User IDs assigned to the shift                                   |
| `startTime`              | integer    | Always   | Unix timestamp of shift start                                    |
| `endTime`                | integer    | Always   | Unix timestamp of shift end                                      |
| `timezone`               | string     | Always   | IANA timezone (e.g. `"America/New_York"`)                        |
| `allDay`                 | boolean    | Always   | Whether this is an all-day shift                                 |
| `isOpenShift`            | boolean    | Always   | Whether this is an open shift (claimable by employees)           |
| `isPublished`            | boolean    | Always   | Whether the shift is visible to employees                        |
| `isRequireAdminApproval` | boolean    | Optional | Whether open-shift claims require admin approval                 |
| `jobId`                  | string     | Optional | Associated job ID                                                |
| `locationData`           | object     | Optional | Location information — see below                                 |
| `createdBy`              | integer    | Optional | User ID of the shift creator                                     |
| `creationTime`           | integer    | Optional | Unix timestamp of creation                                       |
| `updateTime`             | integer    | Optional | Unix timestamp of last update                                    |
| `openSpots`              | integer    | Optional | Number of open spots. Only present when `isOpenShift` is `true`. |
| `notes`                  | array      | Always   | Shift notes — see below                                          |
| `statuses`               | array      | Always   | User statuses for this shift — see below                         |
| `breaks`                 | array      | Always   | Scheduled breaks — see below                                     |
| `shiftDetails`           | object     | Always   | Additional details including shift layers — see below            |
| `customFields`           | array      | Always   | Custom field values — see below                                  |

***

### locationData

Location information attached to the shift.

```json
{
  "isReferencedToJob": true,
  "gps": {
    "address": "Times Square, Manhattan, NY, USA",
    "longitude": -73.9855426,
    "latitude": 40.7579747
  }
}
```

| Field               | Type    | Description                                                                        |
| :------------------ | :------ | :--------------------------------------------------------------------------------- |
| `isReferencedToJob` | boolean | Whether the location is inherited from the associated job                          |
| `gps`               | object  | GPS 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**.

```json
{
  "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
  }
}
```

| Field             | Type      | Description                                                                                                                                                |
| :---------------- | :-------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `statusId`        | string    | Unique status record ID                                                                                                                                    |
| `status`          | string    | One of: `accepted`, `rejected`, `checked_in`, `completed`, `claimed`, `claim_requested`, `unclaimed`, `unclaim_requested`, `cancel_claim_request`, `reset` |
| `assignedUserId`  | integer   | The user this status belongs to                                                                                                                            |
| `creatingUserId`  | integer   | User who created the status                                                                                                                                |
| `modifyingUserId` | integer   | User who last modified the status (optional)                                                                                                               |
| `creationTime`    | integer   | Unix timestamp of status creation (optional)                                                                                                               |
| `updateTime`      | integer   | Unix timestamp of last status update (optional)                                                                                                            |
| `note`            | string    | Status note text (optional)                                                                                                                                |
| `attachments`     | string\[] | Attachment identifiers (optional)                                                                                                                          |
| `gps`             | object    | GPS data at time of status change (optional)                                                                                                               |

***

### breaks

Scheduled break periods within the shift.

```json
{
  "id": "brk-001",
  "name": "Lunch Break",
  "type": "unpaid",
  "startTime": 720,
  "duration": 30
}
```

| Field       | Type    | Description                                                                                              |
| :---------- | :------ | :------------------------------------------------------------------------------------------------------- |
| `id`        | string  | Unique break ID                                                                                          |
| `name`      | string  | Break name                                                                                               |
| `type`      | string  | `"paid"` or `"unpaid"`                                                                                   |
| `startTime` | integer | Minutes from the start of the day (e.g. `720` = 12:00 PM). Optional — may be absent for flexible breaks. |
| `duration`  | integer | Break 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:**

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

**File attachment:**

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

**Image album:**

```json
{
  "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.

```json
{
  "shiftLayers": [
    {
      "id": "layer-dept",
      "title": "Department",
      "value": {
        "id": "val-kitchen",
        "displayName": "Kitchen"
      }
    }
  ]
}
```

| Field         | Type   | Description                                                                                                                                             |
| :------------ | :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `shiftLayers` | array  | Shift layer assignments. Each entry has `id` (layer definition ID), `title` (display name), and `value` (selected instance with `id` and `displayName`) |
| `shiftSource` | string | Source 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:**

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

**Dropdown custom field:**

```json
{
  "customFieldId": 43,
  "name": "Skill Level",
  "type": "dropdown",
  "value": [
    { "id": 1, "value": "Advanced" }
  ]
}
```

| Field           | Type    | Description                                                                             |
| :-------------- | :------ | :-------------------------------------------------------------------------------------- |
| `customFieldId` | integer | Custom field definition ID                                                              |
| `name`          | string  | Custom field label                                                                      |
| `type`          | string  | Field type — `"str"` or `"dropdown"`                                                    |
| `value`         | varies  | Text 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

```json
{
  "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

```json
{
  "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

| Field           | Type    | Description                                              |
| :-------------- | :------ | :------------------------------------------------------- |
| `id`            | string  | Unique availability record ID                            |
| `type`          | string  | `"available"` or `"unavailable"`                         |
| `userId`        | integer | The user this status belongs to                          |
| `start`         | object  | Start time with `timestamp` (Unix) and `timezone` (IANA) |
| `end`           | object  | End time with `timestamp` (Unix) and `timezone` (IANA)   |
| `isAllDay`      | boolean | Whether this covers the entire day                       |
| `note`          | string  | Optional note from the user                              |
| `isAdminAction` | boolean | `true` if set by an admin on behalf of the user          |

***

[API Reference](https://developer.connecteam.com/reference/)