
## Обновить сотрудника

`PATCH /v1/users/:id`

Обновляет поля существующего сотрудника. Передавайте только изменяемые поля. Требует прав администратора портала на стороне Битрикс24 — без них вызов отклоняется.

## Поля запроса (body)

| Параметр | Тип | Описание |
|----------|-----|---------|
| `workPosition` | string | Должность |
| `departmentId` | number[] | Массив ID отделов. Список: `GET /v1/departments` |
| `email` | string | Email — должен оставаться уникальным на портале |
| `workPhone` / `personalPhone` / `personalMobile` | string | Телефоны |
| `active` | boolean | Реактивировать (`true`) или деактивировать (`false`) — деактивация эквивалентна [`DELETE /v1/users/:id`](/docs/entities/users/delete) |

Полный список полей — [Поля сотрудника](/docs/entities/users/fields). Пользовательские (`UF_*`) поля принимаются.

### Фотография профиля

`personalPhoto` — единственное поле сотрудника, которое читается и пишется по-разному: на
чтение приходит URL фотографии, на запись передаётся сам файл — массив ровно из двух
непустых строк: **имя файла и содержимое в base64**.

```json
{ "personalPhoto": ["avatar.png", "iVBORw0KGgoAAAANSUhEUg..."] }
```

Форма работает на `PATCH /v1/users/:id` и `POST /v1/users`. Ответ на неё — обычный ответ
обновления; чтобы убедиться, что фотография заменилась, перечитайте сотрудника и сравните
URL: Битрикс24 хранит файлы по содержимому, поэтому повторная загрузка того же изображения
оставляет прежний URL.

Что отклоняется и почему это важно:

- **вложенная форма `{"personalPhoto": {"fileData": [...]}}`** — отклоняется с
  `400 INVALID_PARAMS`. Битрикс24 отвечает на неё успехом и при этом СНИМАЕТ фотографию,
  поэтому пропустить её нельзя;
- **пустая строка `{"personalPhoto": ""}`** — доходит до портала и снимает фотографию,
  отвечая успехом. Это штатная семантика очистки поля в Битрикс24 — учитывайте её, если
  собираете тело запроса из формы;
- **пакетные маршруты** (`POST /v1/users/batch`, `POST /v1/batch`) фотографию отклоняют:
  подзапрос пакета едет строкой запроса — base64 кодируется дважды, а сами пакетные
  маршруты остались на общем потолке тела, тогда как одиночные подняты до 40 МиБ. За
  пределом длины подзапроса значение обрезалось бы, а обрезанная запись всё равно
  отвечает успехом. Отправляйте фотографию одиночным вызовом;
- **непригодное содержимое или расширение** (`.svg`, `.php`, испорченный base64) отклоняет
  сам портал — `422` с сообщением «Неверный тип файла», фотография при этом не меняется.

## Примеры

### curl — личный ключ

```bash
curl -X PATCH "https://vibecode.bitrix24.tech/v1/users/29" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workPosition": "Старший менеджер",
    "departmentId": [1, 47]
  }'
```

### curl — OAuth-приложение

```bash
curl -X PATCH "https://vibecode.bitrix24.tech/v1/users/29" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workPosition": "Старший менеджер",
    "departmentId": [1, 47]
  }'
```

### JavaScript — личный ключ

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/users/29', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    workPosition: 'Старший менеджер',
    departmentId: [1, 47],
  }),
})

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

### JavaScript — OAuth-приложение

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/users/29', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    workPosition: 'Старший менеджер',
    departmentId: [1, 47],
  }),
})

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

## Поля ответа

| Поле | Тип | Описание |
|------|-----|---------|
| `success` | boolean | Всегда `true` при успехе |
| `data` | object | Обновлённый объект сотрудника со всеми полями — формат тот же, что у [`GET /v1/users/:id`](/docs/entities/users/get) |

## Пример ответа

```json
{
  "success": true,
  "data": {
    "id": 29,
    "name": "Иван",
    "lastName": "Петров",
    "email": "ivan.petrov@example.com",
    "active": true,
    "workPosition": "Старший менеджер",
    "departmentId": [1, 47],
    "userType": "employee"
  }
}
```

## Пример ответа при ошибке

403 — обновление отклонено Битрикс24:

```json
{
  "success": false,
  "error": {
    "code": "UPDATE_FAILED",
    "message": "Bitrix24 rejected user.update (result: false)",
    "hint": "Bitrix24 returns false when the calling user lacks portal admin rights, when a read-only field was touched (isOnline, lastLogin, dateRegister, isAdmin), or when the target user ID does not exist. Verify the webhook/OAuth identity is a portal admin."
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|---------|
| 400 | `INVALID_ID` | `:id` не является положительным целым числом |
| 400 | `READONLY_FIELD` | В теле запроса передано readonly-поле (`id`, `isOnline`, `isAdmin`, `lastLogin`, `dateRegister`, `lastActivityDate`, `userType`, `timestampX`). Вайбкод отклоняет до вызова Битрикс24 |
| 400 | `BITRIX_ERROR` | Битрикс24 отклонил поле — например, `wrong_email` при попытке поставить уже занятый email |
| 401 | `TOKEN_MISSING` | API-ключ не имеет настроенных токенов |
| 403 | `SCOPE_DENIED` | API-ключ не имеет скоупа `user` |
| 403 | `UPDATE_FAILED` | Битрикс24 вернул `result: false` для запроса на обновление. Чаще всего — у владельца ключа нет прав администратора портала |

Полный список общих ошибок API — [Ошибки](/docs/errors).

## Известные особенности

**Изменение email.** Если новый email уже занят другим сотрудником портала, Битрикс24 вернёт `BITRIX_ERROR: wrong_email`. Перед PATCH — проверка через `GET /v1/users?filter[EMAIL]=новый@example.com`.

## Смотрите также

- [Получить сотрудника](/docs/entities/users/get)
- [Поля сотрудника](/docs/entities/users/fields)
- [Деактивировать сотрудника](/docs/entities/users/delete)
- [Batch](/docs/batch)
- [Лимиты и оптимизация](/docs/optimization)
