## Create a schedule

`POST /v1/work-schedules`

Creates a custom work schedule in the library of the Bitrix24 account.

The created schedule is assigned to servers by [setting the run mode](/docs/infra/lifecycle/run-mode).

## Request fields (body)

| Field | Type | Required | Description |
|------|-----|:-----:|----------|
| `name` | string | yes | Name, from 1 to 80 characters. Leading and trailing spaces are dropped |
| `timezone` | string | yes | IANA time zone the windows are read in, for example `Europe/Berlin` |
| `windows` | array | yes | Windows `{ isoDay, start, end }`, at most two per day. Window rules are on the [section index](/docs/infra/work-schedules) |
| `windows[].isoDay` | number | yes | Weekday: 1 — Monday, 7 — Sunday |
| `windows[].start` | string | yes | Window start, local `HH:MM` on a 30-minute step |
| `windows[].end` | string | yes | Window end, local `HH:MM` on a 30-minute step. Midnight is `24:00` |

## Examples

### curl — personal key

```bash
curl -X POST https://vibecode.bitrix24.com/v1/work-schedules \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Warehouse shifts",
    "timezone": "Europe/Berlin",
    "windows": [
      { "isoDay": 1, "start": "09:00", "end": "18:00" },
      { "isoDay": 2, "start": "09:00", "end": "13:00" },
      { "isoDay": 2, "start": "14:00", "end": "24:00" }
    ]
  }'
```

### curl — OAuth application

```bash
curl -X POST https://vibecode.bitrix24.com/v1/work-schedules \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Warehouse shifts",
    "timezone": "Europe/Berlin",
    "windows": [
      { "isoDay": 1, "start": "09:00", "end": "18:00" },
      { "isoDay": 2, "start": "09:00", "end": "13:00" },
      { "isoDay": 2, "start": "14:00", "end": "24:00" }
    ]
  }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/work-schedules', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Warehouse shifts',
    timezone: 'Europe/Berlin',
    windows: [
      { isoDay: 1, start: '09:00', end: '18:00' },
      { isoDay: 2, start: '09:00', end: '13:00' },
      { isoDay: 2, start: '14:00', end: '24:00' },
    ],
  }),
})
const { data } = await res.json()
console.log(`Created schedule ${data.id}`)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/work-schedules', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Warehouse shifts',
    timezone: 'Europe/Berlin',
    windows: [
      { isoDay: 1, start: '09:00', end: '18:00' },
      { isoDay: 2, start: '09:00', end: '13:00' },
      { isoDay: 2, start: '14:00', end: '24:00' },
    ],
  }),
})
const { data } = await res.json()
```

## Response fields

The response comes with status `201 Created`.

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success |
| `data.id` | string | ID of the created schedule |
| `data.kind` | string | Always `CUSTOM` |
| `data.name` | string | Name |
| `data.presetKey` | null | Always `null` for a custom schedule |
| `data.timezone` | string | IANA time zone |
| `data.windows` | array | Windows `{ isoDay, start, end }` ordered by day and time |
| `data.version` | number | Version number, `1` for a new schedule |
| `data.canEdit` | boolean | `true`: the author may edit their own schedule |
| `data.assignedCount` | number | `0`: a new schedule is not assigned to anyone yet |

## Response example

```json
{
  "success": true,
  "data": {
    "id": "cmfp4r0q2000a1ocg7h2k9x3d",
    "kind": "CUSTOM",
    "name": "Warehouse shifts",
    "presetKey": null,
    "timezone": "Europe/Berlin",
    "windows": [
      { "isoDay": 1, "start": "09:00", "end": "18:00" },
      { "isoDay": 2, "start": "09:00", "end": "13:00" },
      { "isoDay": 2, "start": "14:00", "end": "24:00" }
    ],
    "version": 1,
    "canEdit": true,
    "assignedCount": 0
  }
}
```

## Error response example

400 — a window time is not in `HH:MM` form:

```json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "windows.0.end: must be local time HH:MM (24:00 for midnight)"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 400 | `VALIDATION_ERROR` | The body does not fit the schema — an unknown field, an empty name, an unknown time zone, a time not in `HH:MM` form — or the windows break the week rules. `message` carries the field path and the reason |
| 400 | `WORK_SCHEDULE_EMPTY` | An empty `windows` was passed: a server on such a schedule would never run |
| 400 | `RUN_MODE_UNAVAILABLE` | Run modes are not enabled for the Bitrix24 account yet |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `INVALID_API_KEY` | The key is not recognized: no such key exists on the platform |
| 403 | `WORK_SCHEDULE_LIMIT` | The Bitrix24 account already keeps 50 custom schedules. Delete an unused one or assign a preset |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only — creating is closed to it |
| 403 | `INFRA_SCOPE_REQUIRED` | The key lacks the `vibe:infra` scope |
| 403 | `INFRA_FORBIDDEN_FOR_COWORK_KEY` | The call was made with a Cowork/Code key — the schedule library is closed to such a key. What to do — [Project deploy key](/docs/cowork/deploy-key) |
| 404 | `NOT_FOUND` | The key is not bound to a Bitrix24 account |
| 429 | `RATE_LIMITED` | The limit of 20 requests per minute per key is exceeded. The exact value is in the `x-ratelimit-limit` header (the ceiling is split between replicas) |

Full list of shared error codes — [Errors](/docs/errors).

## Known specifics

- **The author is the key owner.** The schedule's author is recorded as the key owner, not the user of an OAuth application session. Later the schedule can be edited and deleted by them and by an administrator of the Bitrix24 account.
- **Presets do not count toward the limit.** The limit of 50 schedules counts custom schedules only; platform presets take no place in it.

## See also

- [List schedules](./list.md)
- [Update a schedule](./update.md)
- [Set the server run mode](/docs/infra/lifecycle/run-mode)
