
## Update event

`PATCH /v1/calendar-events/:id`

Updates fields of an existing event. Pass only the fields being changed — Vibecode automatically reads the current event and supplies `type`, `ownerId`, `name`, which Bitrix24 requires on every update.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|---------|
| `id` (path) | number | yes | Event ID. List: [`GET /v1/calendar-events`](./list.md) |

## Request fields (body)

All fields are optional. Pass only the ones you change, for example `name` or `location`. For an all-day event, you can change only `from` or only `to`: the omitted boundary is preserved. Pass the new dates of such an event with a time and the offset of the API key owner's timezone — a date without a time can move the event to an adjacent day, see [Create event](./create.md#known-specifics).

| Field | Type | Required | Description |
|------|-----|:-----:|---------|
| `name` | string | no | Event title. If omitted, taken from the current event |
| `type` | string | no | Calendar type: `user`, `group`, `company_calendar`. If omitted, taken from the current event |
| `ownerId` | number | no | Calendar owner ID: an employee (`GET /v1/users`) or a workgroup. If omitted, taken from the current event |
| `from` | datetime | no | New event start in ISO 8601. Pass together with `timezoneFrom` |
| `timezoneFrom` | string | no | Start timezone (IANA name, `UTC`) |
| `to` | datetime | no | New event end in ISO 8601. Pass together with `timezoneTo` |
| `timezoneTo` | string | no | End timezone (IANA name, `UTC`) |
| `skipTime` | boolean | no | All-day event. When `true`, the event covers the calendar days from `from` through `to`, inclusive. If omitted, the current flag is preserved; `false` clears it |
| `description` | string | no | Description |
| `location` | string | no | Venue |
| `color` | string | no | Event color in `#RRGGBB` format |
| `importance` | string | no | Importance: `high`, `normal`, `low` |
| `accessibility` | string | no | Availability: `busy`, `quest`, `free`, `absent` |
| `isPrivate` | boolean | no | Private event — details are hidden from other users |
| `sectionId` | number | no | ID of the calendar section to move the event to. Section list: [`GET /v1/calendar-sections`](/docs/entities/calendar-sections/list) |
| `remind` | array | no | Reminder settings. Each element: `{type: 'min' \| 'hour' \| 'day', count: <number>}` |
| `rrule` | object | no | Recurrence schedule: `FREQ`, `INTERVAL`, `BYDAY`, `UNTIL` or `COUNT`. Structure — [Create event](./create.md#recurring-event) |
| `attendees` | number[] | no | Array of invited employee IDs. List: `GET /v1/users`. Pass it together with `isMeeting: true` — without the flag in the body the array is ignored with no error and no warning, even if the event is already a meeting. The array you send replaces the previous attendee list entirely. Whether the IDs exist is not checked: any number becomes an attendee `U<id>`. CRM elements are linked with the `crmFields` field |
| `isMeeting` | boolean | no | Marks the event as a meeting with invitations. Required in the body together with `attendees`, otherwise the attendee list does not change |
| `crmFields` | string[] | no | CRM elements the event is linked to: `D_<id>` deal, `C_<id>` contact, `L_<id>` lead, `CO_<id>` company. The array you send replaces the previous links entirely, `[]` clears them all — but only on this endpoint and on `POST`: in a batch request an empty array is refused (`INVALID_PARAMS` in `data.errors` on `POST /v1/batch`, `400 BATCH_ITEM_VALIDATION` for the whole batch on `POST /v1/calendar-events/batch`). A field left out of the body keeps the links already stored. Full description — [Event fields](./fields.md) |

Description of all event fields — [Event fields](./fields.md).

## Examples

### curl — personal key

```bash
curl -X PATCH "https://vibecode.bitrix24.com/v1/calendar-events/7773" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Team call — extended meeting",
    "to": "2026-06-10T12:00:00",
    "timezoneTo": "UTC",
    "location": "Meeting room #3"
  }'
```

### curl — OAuth application

```bash
curl -X PATCH "https://vibecode.bitrix24.com/v1/calendar-events/7773" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Team call — extended meeting",
    "to": "2026-06-10T12:00:00",
    "timezoneTo": "UTC",
    "location": "Meeting room #3"
  }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/calendar-events/7773', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Team call — extended meeting',
    to: '2026-06-10T12:00:00',
    timezoneTo: 'UTC',
    location: 'Meeting room #3',
  }),
})

const { success, data } = await res.json()
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/calendar-events/7773', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Team call — extended meeting',
    to: '2026-06-10T12:00:00',
    timezoneTo: 'UTC',
    location: 'Meeting room #3',
  }),
})

const { success, data } = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data` | object | The updated event (all fields — see [Event fields](./fields.md)) |

## Response example

```json
{
  "success": true,
  "data": {
    "id": 7773,
    "parentId": 7773,
    "type": "user",
    "ownerId": 1,
    "name": "Team call — extended meeting",
    "from": "2026-06-10T10:00:00+00:00",
    "to": "2026-06-10T12:00:00+00:00",
    "skipTime": false,
    "durationSeconds": 7200,
    "updatedAt": "06/05/2026 11:30:00 am",
    "accessibility": "busy",
    "importance": "normal",
    "sectionId": 3,
    "location": "Meeting room #3"
  }
}
```

## Error response example

404 — event not found:

```json
{
  "success": false,
  "error": {
    "code": "ENTITY_NOT_FOUND",
    "message": "calendarEvent 99999999 not found"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 404 | `ENTITY_NOT_FOUND` | The event with the specified `id` does not exist |
| 400 | `READONLY_FIELD` | A read-only field was passed in the request body — the full list is in [Event fields](./fields.md), where such fields are marked "yes" in the RO column |
| 400 | `EMPTY_UPDATE_BODY` | The request body is empty — pass at least one field |
| 422 | `BITRIX_NO_EFFECT` | The portal did not return the all-day flag or a date needed for a safe update |
| 400 | `NESTED_FIELDS_ENVELOPE` | The body contains an object under `fields` instead of root-level fields; the event is not updated |
| 403 | `SCOPE_DENIED` | The API key does not have the `calendar` scope |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |

Full list of common API errors — [Errors](/docs/errors).

## Known specifics

**An object under `fields` does not wrap event fields.** Pass them at the JSON root: the schema does not declare `fields`, so the object is rejected with `400 NESTED_FIELDS_ENVELOPE` before the update.

**An unknown scalar field in the body is ignored without an error.** A `200` response does not confirm the field was written. Check field names against the table above.

## See also

- [Get event](./get.md)
- [Event fields](./fields.md)
- [Create event](./create.md)
- [Delete event](./delete.md)
