---
updatedAt: 2026-06-29T07:49:45.000Z
---

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

# Creating Shifts

Create single or multiple shifts in a scheduler. This endpoint supports bulk creation of up to 500 shifts per request.

> 📘 JS Vision (Scheduler V2)
>
> This page documents the standard **V1** API, available on all companies. Assigning **multiple users** to one shift and setting **`openSpots` greater than 1** require **Scheduler V2** on a JS Vision–migrated company — see [JS Vision: V1 vs V2 Shifts API](https://developer.connecteam.com/docs/scheduler-shifts-vision).

## Endpoint

| Method | Endpoint                                      | Description               |
| :----- | :-------------------------------------------- | :------------------------ |
| POST   | /scheduler/v1/schedulers/{schedulerId}/shifts | Create one or more shifts |

***

## Path Parameters

| Parameter   | Type    | Required | Description               |
| :---------- | :------ | :------- | :------------------------ |
| schedulerId | integer | Yes      | The scheduler's unique ID |

## Query Parameters

| Parameter   | Type    | Default | Description                               |
| :---------- | :------ | :------ | :---------------------------------------- |
| notifyUsers | boolean | true    | Send push notifications to assigned users |

> 📝 Note on Notifications
>
> Notifications are only sent for **published** shifts. Draft shifts (isPublished=false) never trigger notifications regardless of this setting.

***

## Request Body

The request body is an **array** of shift objects. You can create 1 to 500 shifts per request.

### Shift Object Fields

| Field                  | Type    | Required    | Default              | Description                                                                                        |
| :--------------------- | :------ | :---------- | :------------------- | :------------------------------------------------------------------------------------------------- |
| startTime              | integer | **Yes**     | -                    | Start time (Unix timestamp in seconds)                                                             |
| endTime                | integer | **Yes**     | -                    | End time (Unix timestamp in seconds)                                                               |
| title                  | string  | Conditional | -                    | Shift name (required if no `jobId`)                                                                |
| jobId                  | string  | Conditional | -                    | Associated job ID (required if no `title`)                                                         |
| timezone               | string  | No          | Scheduler TZ         | Timezone in Tz format (e.g., `America/New_York`)                                                   |
| isPublished            | boolean | No          | false                | Whether shift is visible to users                                                                  |
| isOpenShift            | boolean | No          | false                | Whether shift is available for claiming                                                            |
| openSpots              | integer | No          | 1                    | Number of claimable spots (open shifts only; values other than 1 require Scheduler V2 / JS Vision) |
| isRequireAdminApproval | boolean | No          | false                | Whether claims require approval (open shifts only)                                                 |
| assignedUserIds        | array   | No          | \[]                  | User IDs to assign                                                                                 |
| locationData           | object  | No          | -                    | Location information                                                                               |
| color                  | string  | No          | Job color or #4B7AC5 | Hex color code                                                                                     |
| notes                  | array   | No          | \[]                  | HTML notes                                                                                         |
| breaks                 | array   | No          | \[]                  | Break definitions                                                                                  |
| statuses               | array   | No          | \[]                  | Initial statuses                                                                                   |
| shiftDetails           | object  | No          | -                    | Shift layer values                                                                                 |
| customFields           | array   | No          | \[]                  | Custom field values                                                                                |

> ⚠️ Required: Title or Job
>
> Every shift must have either a `title` OR a `jobId`. If neither is provided, the request will fail with a 400 error.

***

## Validation Rules

> 🚨 Critical Validation Rules
>
> * **Timestamps must be in seconds** (epoch), not milliseconds. Values > 1e12 will be rejected.
> * **Shift duration cannot exceed 24 hours**
> * **Break total duration cannot exceed shift duration**
> * **Open spots maximum is 100**
> * **Assigned users must exist** and be assigned to the scheduler
> * **Job must be assigned to the scheduler** if jobId is specified

### Assigned Users Rules

| Scenario                  | Rule                                                 |
| :------------------------ | :--------------------------------------------------- |
| Published, non-open shift | Must have at least 1 assigned user                   |
| Open shift                | `assignedUserIds` must be empty                      |
| Draft shift               | Can be empty                                         |
| Multiple users            | Requires Scheduler V2 on a JS Vision-enabled company |

***

## Examples

### Basic Published Shift

```bash
curl --request POST \
  --url 'https://api.connecteam.com/scheduler/v1/schedulers/9454799/shifts?notifyUsers=true' \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '[
    {
      "startTime": 1736924400,
      "endTime": 1736953200,
      "title": "Morning Shift",
      "isPublished": true,
      "assignedUserIds": [9170357]
    }
  ]'
```

### Draft Shift (Not Visible)

```bash
curl --request POST \
  --url 'https://api.connecteam.com/scheduler/v1/schedulers/9454799/shifts' \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '[
    {
      "startTime": 1736924400,
      "endTime": 1736953200,
      "title": "Planning Shift",
      "isPublished": false
    }
  ]'
```

> 💡 Draft Shifts
>
> Draft shifts (isPublished=false) are not visible to users and don't require assigned users. Use them for planning before publishing.

### Open Shift with Admin Approval

```bash
curl --request POST \
  --url 'https://api.connecteam.com/scheduler/v1/schedulers/9454799/shifts' \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '[
    {
      "startTime": 1736924400,
      "endTime": 1736953200,
      "title": "Weekend Coverage",
      "isOpenShift": true,
      "isRequireAdminApproval": true,
      "isPublished": true
    }
  ]'
```

> 📝 Note on Open Shifts
>
> Open shifts default to 1 available spot. Without JS Vision, you cannot specify a custom `openSpots` value.

### Shift with Job and Location Override

```bash
curl --request POST \
  --url 'https://api.connecteam.com/scheduler/v1/schedulers/9454799/shifts' \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '[
    {
      "startTime": 1736924400,
      "endTime": 1736953200,
      "jobId": "d4ad7232-576f-2ff6-c57d-8240f1089b00",
      "isPublished": true,
      "assignedUserIds": [9170357],
      "locationData": {
        "isReferencedToJob": false,
        "gps": {
          "address": "456 Oak Avenue, Brooklyn, NY",
          "latitude": 40.6782,
          "longitude": -73.9442
        }
      }
    }
  ]'
```

> 📝 Location Reference
>
> Set `isReferencedToJob: true` to inherit the job's location. Set `isReferencedToJob: false` and provide `gps` data to override with a custom location.

### Shift with Breaks

```bash
curl --request POST \
  --url 'https://api.connecteam.com/scheduler/v1/schedulers/9454799/shifts' \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '[
    {
      "startTime": 1736924400,
      "endTime": 1736960400,
      "title": "Full Day Shift",
      "isPublished": true,
      "assignedUserIds": [9170357],
      "breaks": [
        {
          "name": "Morning Break",
          "type": "paid",
          "startTime": 600,
          "duration": 15
        },
        {
          "name": "Lunch",
          "type": "unpaid",
          "startTime": 720,
          "duration": 30
        },
        {
          "name": "Afternoon Break",
          "type": "paid",
          "startTime": 900,
          "duration": 15
        }
      ]
    }
  ]'
```

> ⚠️ Break Time Format
>
> Break `startTime` is in **minutes from midnight**, not Unix timestamp.
>
> * 600 = 10:00 AM
> * 720 = 12:00 PM (noon)
> * 900 = 3:00 PM

### Shift with Notes

```bash
curl --request POST \
  --url 'https://api.connecteam.com/scheduler/v1/schedulers/9454799/shifts' \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '[
    {
      "startTime": 1736924400,
      "endTime": 1736953200,
      "title": "Special Event Shift",
      "isPublished": true,
      "assignedUserIds": [9170357],
      "notes": [
        {
          "html": "<p><b>Important:</b> Arrive 15 minutes early for briefing</p>"
        },
        {
          "html": "<p>Dress code: Business casual</p>"
        }
      ]
    }
  ]'
```

### Shift with Shift Layers

```bash
curl --request POST \
  --url 'https://api.connecteam.com/scheduler/v1/schedulers/9454799/shifts' \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '[
    {
      "startTime": 1736924400,
      "endTime": 1736953200,
      "title": "Department Shift",
      "isPublished": true,
      "assignedUserIds": [9170357],
      "shiftDetails": {
        "shiftLayers": [
          {
            "id": "layer-dept-001",
            "value": {
              "id": "value-sales-001"
            }
          }
        ],
        "shiftSource": "API Integration"
      }
    }
  ]'
```

### Shift with Custom Fields

```bash
curl --request POST \
  --url 'https://api.connecteam.com/scheduler/v1/schedulers/9454799/shifts' \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '[
    {
      "startTime": 1736924400,
      "endTime": 1736953200,
      "title": "Project Shift",
      "isPublished": true,
      "assignedUserIds": [9170357],
      "customFields": [
        {
          "id": "field_abc123",
          "value": "PROJ-2024-001"
        },
        {
          "id": "field_def456",
          "value": "CC-Operations"
        }
      ]
    }
  ]'
```

> 📝 Note on Custom Fields
>
> Custom field definitions must be created in the Connecteam UI. Once created, you can set their values via the API. Use the [Get Custom Fields](https://developer.connecteam.com/reference/get-shift-custom-fields) endpoint to retrieve available field IDs.

### Bulk Create (Multiple Shifts)

```bash
curl --request POST \
  --url 'https://api.connecteam.com/scheduler/v1/schedulers/9454799/shifts' \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '[
    {
      "startTime": 1736924400,
      "endTime": 1736953200,
      "title": "Morning Shift",
      "isPublished": true,
      "assignedUserIds": [9170357]
    },
    {
      "startTime": 1736953200,
      "endTime": 1736982000,
      "title": "Afternoon Shift",
      "isPublished": true,
      "assignedUserIds": [9170358]
    },
    {
      "startTime": 1736982000,
      "endTime": 1737010800,
      "title": "Night Shift",
      "isPublished": true,
      "assignedUserIds": [9170359]
    }
  ]'
```

***

## Response

```json
{
  "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "data": {
    "shifts": [
      {
        "id": "6784dacb3c07733b0a849f49",
        "title": "Morning Shift",
        "color": "#4B7AC5",
        "assignedUserIds": [9170357],
        "startTime": 1736924400,
        "endTime": 1736953200,
        "timezone": "America/New_York",
        "isOpenShift": false,
        "isPublished": true,
        "isRequireAdminApproval": false,
        "jobId": null,
        "locationData": null,
        "createdBy": 9170357,
        "creationTime": 1736760011,
        "updateTime": 1736760011,
        "openSpots": null,
        "notes": [],
        "statuses": [],
        "breaks": [],
        "shiftDetails": {
          "shiftLayers": [],
          "shiftSource": null
        },
        "customFields": []
      }
    ]
  }
}
```

***

## Error Responses

### 400 Bad Request

**Missing title and jobId:**

```json
{
  "detail": "Shift must have either title or specified job ID"
}
```

**Invalid user:**

```json
{
  "detail": {
    "shift-0": ["assigned user ids doesn't exist: [99999999]"]
  }
}
```

**Shift too long:**

```json
{
  "detail": "Shifts can't be more than 24 hours"
}
```

**Breaks exceed shift duration:**

```json
{
  "detail": "The total duration of breaks cannot exceed the duration of the shift."
}
```

**Timestamp in milliseconds:**

```json
{
  "detail": "start_time and end_time must be in epoch time format"
}
```

**Open spots on non-open shift:**

```json
{
  "detail": "open_spots can be set only for open shifts"
}
```

**Open spots exceed limit:**

```json
{
  "detail": "open_spots must not exceed 100"
}
```

***

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