
## Add participants

`POST /v1/bots/:botId/chats/:dialogId/users`

Adds users to a chat. After the add call, Vibecode makes a best-effort check of the chat roster against the requested list and reports anyone missing in the `warning` field of the successful response. The check is not guaranteed: when it does not run, the response arrives without `warning`.

## Request fields (body)

| Parameter | Type | Req. | Description |
|----------|-----|:-----:|---------|
| `userIds` | number[] | yes | Array of user IDs to add |

## Examples

### curl — personal key

```bash
curl -X POST https://vibecode.bitrix24.com/v1/bots/42/chats/chat456/users \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "userIds": [5, 12] }'
```

### curl — OAuth application

```bash
curl -X POST https://vibecode.bitrix24.com/v1/bots/42/chats/chat456/users \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "userIds": [5, 12] }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/bots/42/chats/chat456/users', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ userIds: [5, 12] }),
})

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

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/bots/42/chats/chat456/users', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ userIds: [5, 12] }),
})

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

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `data.result` | boolean | Bitrix24's acknowledgement that the request was accepted. It is `true` even when no one ended up in the chat — the actual outcome is shown by `warning` |
| `warning` | object | Present when the check ran and found that at least one of the requested users did not end up in the chat — including the case where none of them did. The absence of the field does not prove that everyone was added |
| `warning.code` | string | Always `USERS_NOT_ADDED` |
| `warning.message` | string | Explains why the addition may not have gone through |
| `warning.notAdded` | number[] | Identifiers from `userIds` that are not in the chat roster |
| `warning.addedAtLeast` | number | How many of the requested users were added |

## Response example

```json
{
  "success": true,
  "data": {
    "result": true
  }
}
```

The request included inactive employee `27` — Bitrix24 reported success, the employee did not end up in the chat, and the response carries a `warning`:

```json
{
  "success": true,
  "data": {
    "result": true
  },
  "warning": {
    "code": "USERS_NOT_ADDED",
    "message": "Bitrix24 returned success but 1 of 1 requested user(s) were not added to the chat — likely missing permissions, extranet restriction, or user not on portal.",
    "notAdded": [27],
    "addedAtLeast": 0
  }
}
```

## Error response example

403 — the bot belongs to a different key:

```json
{
  "success": false,
  "error": {
    "code": "BOT_ACCESS_DENIED",
    "message": "This bot belongs to a different API key"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_BOT_ID` | `botId` is not a number |
| 404 | `BOT_NOT_FOUND` | No bot found with this ID |
| 403 | `BOT_ACCESS_DENIED` | The bot belongs to another API key |
| 502 | `BITRIX_ERROR` | Bitrix24 error (error text in `message`) |
| 403 | `SCOPE_DENIED` | The API key does not have the `imbot` scope |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |

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

## Known specifics

**The response stays successful even when not everyone is added.** Inactive employees and non-existent identifiers never end up in the chat. Missing permissions and extranet restrictions can also be the cause. The HTTP status stays successful in that case and `data.result` is `true` — the ones left out are listed in `warning.notAdded`. Check the response for `warning`, not just `success`.

**The roster check is best-effort.** The participant list is requested with a separate call after the add call. When that call does not go through, the response arrives as a plain success without `warning` — so the absence of `warning` does not prove that everyone ended up in the chat. When the roster matters, request it explicitly: [List participants](/docs/bots/chats/user-list).

## See also

- [Remove a participant](/docs/bots/chats/user-delete)
- [List participants](/docs/bots/chats/user-list)
- [Bot platform](/docs/bots)
- [Limits and optimization](/docs/optimization)
