## Add an employee to a CRM chat

`POST /v1/openlines/crm/chats/users`

Adds an employee to an Open Channels chat linked to a lead, deal, contact or company, so a colleague can join the conversation about the CRM card.

## Request fields (body)

| Field | Type | Required | Description |
|------|-----|:-----:|---------|
| `crmEntityType` | string | yes | CRM object type: `lead`, `deal`, `company`, `contact`. Case-insensitive |
| `crmEntityId` | number | yes | CRM object ID, a positive integer. List: [`GET /v1/leads`](/docs/entities/leads/list), [`GET /v1/deals`](/docs/entities/deals/list), [`GET /v1/companies`](/docs/entities/companies/list), [`GET /v1/contacts`](/docs/entities/contacts/list) |
| `userId` | number | yes | ID of the employee to add to the chat. List: [`GET /v1/users`](/docs/entities/users/list) |
| `chatId` | number | no | ID of an Open Channels chat of this CRM object. List: [`GET /v1/openlines/crm/chats`](/docs/openlines/crm-chats) with `activeOnly=false`. If omitted, the object's last chat is used |

## Examples

### curl — personal key

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/openlines/crm/chats/users" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"crmEntityType": "deal", "crmEntityId": 42, "userId": 7, "chatId": 123}'
```

### curl — OAuth application

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/openlines/crm/chats/users" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"crmEntityType": "deal", "crmEntityId": 42, "userId": 7, "chatId": 123}'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/openlines/crm/chats/users', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    crmEntityType: 'deal',
    crmEntityId: 42,
    userId: 7,
    chatId: 123,
  }),
})

const { success, data } = await res.json()
console.log('Chat:', data.chatId)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/openlines/crm/chats/users', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    crmEntityType: 'deal',
    crmEntityId: 42,
    userId: 7,
    chatId: 123,
  }),
})

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

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | `true` when the employee is added |
| `data.chatId` | number | ID of the chat the employee was added to. If `chatId` is omitted, this is the CRM object's last chat |
| `data.userId` | number | ID of the added employee |
| `data.added` | boolean | Always `true` |

## Response example

```json
{
  "success": true,
  "data": {
    "chatId": 123,
    "userId": 7,
    "added": true
  }
}
```

## Error response example

404 — the CRM object has no chat with the given `chatId`:

```json
{
  "success": false,
  "error": {
    "code": "ENTITY_NOT_FOUND",
    "message": "CRM chat not found"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 400 | `INVALID_PARAMS` | The body is not a JSON object, `crmEntityType` is missing or not in the list, `crmEntityId` or `userId` is missing or not a positive integer |
| 400 | `INVALID_JSON_BODY` | The request body cannot be parsed as JSON |
| 400 | `INVALID_CHAT_ID` | `chatId` is passed but is not a positive integer |
| 404 | `ENTITY_NOT_FOUND` | Message `CRM chat not found`: the CRM object has no Open Channels chats, including finished ones, or `chatId` is not one of them. The check runs before the write, so chat membership does not change |
| 404 | `ENTITY_NOT_FOUND` | Message `Record not found`: Bitrix24 did not find the chat when adding the employee |
| 422 | `BITRIX_ERROR` | `error.b24Code` equals `CHAT_NOT_IN_CRM`: Bitrix24 did not confirm that the chat is linked to the CRM object |
| 422 | `BITRIX_ERROR` | Bitrix24 rejected the request for another reason. The text is in `message` |
| 403 | `BITRIX_ACCESS_DENIED` | Bitrix24 denied the key owner due to insufficient permissions |
| 403 | `SCOPE_DENIED` | The key does not have the `imopenlines` scope |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The key is read-only |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not passed |
| 401 | `INVALID_API_KEY` | The key is not recognized |
| 401 | `TOKEN_MISSING` | A personal key has no access to the Bitrix24 portal, or an application key was sent without a session token in `Authorization` |
| 429 | `RATE_LIMITED` | The limit of 120 requests per minute per portal is exceeded. The limit is divided across platform replicas, so the code may arrive before the 120th request. The effective value for the key is in the `x-ratelimit-limit` header, the remaining quota in `x-ratelimit-remaining` |
| 429 | `RATE_LIMITED` | Bitrix24 rejected the call under its request rate limit for the portal. The response carries a `Retry-After` header |
| 502 | `OPENLINE_OPERATOR_FAILED` | Bitrix24 returned an unexpected write result: not a chat ID, or a chat other than the passed `chatId` |
| 502 | `OPENLINE_OPERATOR_FAILED` | The card's chat list arrived in an unexpected shape. The check runs before the write, so chat membership does not change |
| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable |
| 503 | `BITRIX_TIMEOUT` | Bitrix24 did not respond in time, so the result is unknown. Check the chat membership before retrying |

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

## See also

- [Remove an employee from a CRM chat](/docs/openlines/crm/members-delete)
- [CRM chat members](/docs/openlines/crm/members)
- [Chats by CRM card](/docs/openlines/crm-chats)
- [Send a message to the client](/docs/openlines/crm/messages)
