## Изменить роль участников

`PATCH /v1/workgroups/:groupId/users`

Назначает участникам рабочей группы роль модератора или возвращает им роль участника. Одна роль применяется сразу ко всем пользователям из `userIds`.

## Параметры

| Параметр | Тип | Обяз. | Описание |
|----------|-----|:-----:|----------|
| `groupId` (path) | number | да | Идентификатор рабочей группы — положительное целое число. Список: [`GET /v1/workgroups`](/docs/entities/workgroups/list) |

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

| Поле | Тип | Обяз. | Описание |
|------|-----|:-----:|----------|
| `userIds` | number[] | да | Непустой массив идентификаторов участников группы — положительных целых чисел. Состав группы: [`GET /v1/workgroups/:groupId/users`](/docs/entities/workgroups/users) |
| `role` | string | да | Новая роль: `moderator` — модератор, `member` — участник. В составе группы они видны как `E` и `K` |

## Примеры

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

```bash
curl -X PATCH "https://vibecode.bitrix24.tech/v1/workgroups/157/users" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"userIds": [93], "role": "moderator"}'
```

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

```bash
curl -X PATCH "https://vibecode.bitrix24.tech/v1/workgroups/157/users" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"userIds": [93], "role": "moderator"}'
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/workgroups/157/users', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ userIds: [93], role: 'moderator' }),
})

const body = await res.json()
if (!body.success && body.error.code === 'BITRIX_ERROR') {
  if (Array.isArray(body.error.processedUserIds)) {
    // Часть ролей могла смениться — изменения не откатываются
    console.log('Роль изменена:', body.error.processedUserIds)
    console.log('Роль не изменена:', body.error.skippedUserIds)
  } else {
    // Второй вариант 422: Битрикс24 отказал в вызове, массивов в ответе нет
    console.log('Битрикс24 отказал:', body.error.message)
  }
}
```

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

```javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/workgroups/157/users', {
  method: 'PATCH',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ userIds: [93], role: 'moderator' }),
})

const body = await res.json()
```

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

| Поле | Тип | Описание |
|------|-----|----------|
| `success` | boolean | `true`, когда роль изменена у всех запрошенных пользователей |
| `data.groupId` | number | Идентификатор рабочей группы |
| `data.processedUserIds` | number[] | Идентификаторы пользователей, получивших новую роль. Повторы из `userIds` схлопываются в один |
| `data.skippedUserIds` | number[] | В успешном ответе всегда пустой массив. Если роль изменилась не у всех, приходит `422 BITRIX_ERROR`, а оба массива переезжают в `error`. Это единственный ответ с массивами: у второго `422 BITRIX_ERROR` — когда Битрикс24 отказал в вызове — в `error` только его собственный текст, без `processedUserIds` и `skippedUserIds` |

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

```json
{
  "success": true,
  "data": {
    "groupId": 157,
    "processedUserIds": [93],
    "skippedUserIds": []
  }
}
```

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

422 — запрошена роль `member`: у пользователя `93` она сменилась, у владельца группы `1` — нет:

```json
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "Bitrix24 did not change every requested user: existing membership or role, owner, scrum master, missing user or permissions may prevent the action. Do not blindly retry invitations.",
    "processedUserIds": [93],
    "skippedUserIds": [1]
  }
}
```

## Ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 400 | `INVALID_PARAMS` | `groupId` не является положительным целым числом, например `15.7` |
| 400 | `INVALID_PARAMS` | `role` не передан или не равен `moderator` либо `member` |
| 400 | `MISSING_REQUIRED_FIELDS` | `userIds` не передан, пустой или содержит что-то кроме положительных целых чисел |
| 401 | `MISSING_API_KEY` | Не передан `X-Api-Key` |
| 401 | `INVALID_API_KEY` | Ключ не опознан: такой строки на платформе нет |
| 401 | `TOKEN_MISSING` | У ключа нет токенов Битрикс24 |
| 403 | `SCOPE_DENIED` | Ключу не хватает скоупа `sonet_group` |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | Ключ работает в режиме только для чтения |
| 403 | `BITRIX_ACCESS_DENIED` | У пользователя, от имени которого действует ключ, нет прав менять роли в этой группе |
| 404 | `ENTITY_NOT_FOUND` | Группы нет либо она не видна пользователю, от имени которого действует ключ |
| 422 | `BITRIX_ERROR` | Роль изменена не у всех. У кого изменена и у кого нет — в `error.processedUserIds` и `error.skippedUserIds`. Причины пропуска: у пользователя уже эта роль, это владелец группы |
| 422 | `BITRIX_ERROR` | Битрикс24 отказал в вызове и вернул свою причину в `error.message` — например, не принял код роли. Массивов `error.processedUserIds` и `error.skippedUserIds` в этом ответе нет — проверяйте их наличие, прежде чем читать, и перечитайте состав группы перед повтором |
| 429 | `RATE_LIMITED` | Превышен лимит запросов. Пауза — в заголовке `Retry-After` |
| 502 | `BITRIX_UNAVAILABLE` | Битрикс24 недоступен или вернул ответ, который эндпоинт не может разобрать |
| 503 | `BITRIX_TIMEOUT` | Битрикс24 принял вызов, но не ответил вовремя. Есть заголовок `Retry-After`. Перед повтором перечитайте состав группы: роль могла смениться |

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

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

- **Частичный результат не откатывается.** Если часть пользователей пропущена, ответ — `422`, но у тех, кто попал в `error.processedUserIds`, роль уже новая. Проверьте итог через [`GET /v1/workgroups/:groupId/users`](/docs/entities/workgroups/users).
- **Повтор с той же ролью — `422`, а не успех.** Пользователь, у которого роль уже совпадает с запрошенной, попадает в `skippedUserIds`. Чтобы повтор не выглядел ошибкой, сверяйте роли в составе группы перед вызовом.
- **Роль владельца этим вызовом не меняется.** Владельца назначает [`PUT /v1/workgroups/:groupId/owner`](./owner.md).

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

- [Добавить участников](./add.md)
- [Передать владение](./owner.md)
- [Участники рабочей группы](/docs/entities/workgroups/users)
- [Участники рабочих групп](/docs/workgroups/members)
