## Чаты по карточке CRM

`GET /v1/openlines/crm/chats` · `POST /v1/openlines/sessions/intercept` · `POST /v1/openlines/sessions/join`

Три эндпоинта закрывают путь виджета в карточке CRM: найти диалоги открытой линии, привязанные к лиду, сделке, компании или контакту, а затем подключить к найденному диалогу текущего оператора. Все три требуют скоуп `imopenlines`, доступны на любом портале и не ждут обновления `imopenlines 26.700.0`.

Идентификатор `chatId` из ответа первого эндпоинта передаётся во второй и третий без преобразования. Второй источник того же идентификатора — поле `sessions[].chatId` в ответе [Списка сессий](./sessions.md).

**Важно:** `sessions/intercept` и `sessions/join` пишут в живой диалог с клиентом: после вызова оператор становится участником переписки. Права проверяет Битрикс24, и администратор портала проходит эту проверку для любого диалога портала.

## Чаты карточки CRM

`GET /v1/openlines/crm/chats`

### Параметры запроса (query)

| Параметр | Тип | Описание |
|----------|-----|---------|
| `crmEntityType` | string | Обязателен. Один из `lead`, `deal`, `company`, `contact`. Регистр не важен |
| `crmEntityId` | number | Обязателен. Идентификатор объекта CRM, положительное целое |
| `activeOnly` | boolean \| string | Необязателен. `true`, `false`, `Y`, `N`, `1`, `0`. Без параметра приходят только открытые диалоги, `false` добавляет к ним завершённые |

Каждый параметр передаётся ровно один раз и плоским именем: повтор (`crmEntityId=1&crmEntityId=2`) и скобочная форма (`crmEntityId[]=1`) отклоняются ответом `400 INVALID_PARAMS`, а не разрешаются в пользу одного из значений.

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

`data` — массив строк. У объекта без диалогов открытой линии он пустой, и это не ошибка. Так же пустым он приходит, когда объекта с таким `crmEntityId` нет.

| Поле | Тип | Описание |
|------|-----|---------|
| `chatId` | number | Идентификатор чата открытой линии. Передаётся в `sessions/intercept` и `sessions/join` как есть |
| `connectorId` | string \| null | Идентификатор канала, из которого пришёл диалог |
| `connectorTitle` | string \| null | Название канала для показа человеку |

### Пример

```bash
curl "https://vibecode.bitrix24.tech/v1/openlines/crm/chats?crmEntityType=lead&crmEntityId=1001213" \
  -H "X-Api-Key: YOUR_API_KEY"
```

```json
{
  "success": true,
  "data": [
    { "chatId": 4531, "connectorId": "telegrambot", "connectorTitle": "Telegram" }
  ]
}
```

Тот же запрос с `activeOnly=false` по объекту, у которого диалоги уже завершены, отдаёт их в той же форме — например `{ "chatId": 31, "connectorId": "network", "connectorTitle": "Битрикс24 Network" }`.

## Перехват диалога

`POST /v1/openlines/sessions/intercept`

Переводит диалог на текущего оператора: прежний оператор перестаёт быть ведущим по этой сессии.

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/openlines/sessions/intercept" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "chatId": 4531 }'
```

Ответ при успехе: `{ "success": true, "data": { "chatId": 4531, "intercepted": true } }`.

## Вход в диалог

`POST /v1/openlines/sessions/join`

Добавляет текущего оператора в диалог ещё одним участником, не снимая прежнего.

```bash
curl -X POST "https://vibecode.bitrix24.tech/v1/openlines/sessions/join" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "chatId": 4531 }'
```

Ответ при успехе: `{ "success": true, "data": { "chatId": 4531, "joined": true } }`.

Оба эндпоинта принимают `chatId` числом (`4531`) и строкой формы `chat4531`, в ответе идентификатор всегда число. Имя поля — `chatId` или `CHAT_ID`, `dialogId` не принимается.

## Ошибки

| HTTP | Код | Описание |
|:----:|-----|---------|
| 400 | `MISSING_PARAMS` | Не передан обязательный параметр: `crmEntityType`, `crmEntityId` или `chatId` |
| 400 | `INVALID_PARAMS` | Значение параметра недопустимо: `crmEntityType` вне списка, `crmEntityId` не положительное целое, `chatId` не разбирается в идентификатор чата (принимаются положительное целое и форма `chat<N>`), `activeOnly` вне набора допустимых значений. Тот же код, когда параметр запроса передан дважды или в скобочной форме |
| 401 | `TOKEN_MISSING` | У ключа нет настроенных токенов |
| 403 | `SCOPE_DENIED` | У ключа нет скоупа `imopenlines` |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | Ключ работает только на чтение, а `sessions/intercept` и `sessions/join` меняют диалог |
| 403 | `BITRIX_ACCESS_DENIED` | У пользователя ключа нет доступа к объекту CRM или к диалогу |
| 422 | `BITRIX_ERROR` | Битрикс24 отказал, его код приходит в `error.b24Code`. У `sessions/join`: `CHAT_ID` — чата с таким идентификатором нет, `CHAT_TYPE` — чат не является открытой линией. У `sessions/intercept` оба случая дают `OPERATOR_WRONG`. Текст `error.message` приходит от Битрикс24 дословно: для `CHAT_ID` и `CHAT_TYPE` — на языке портала, для `OPERATOR_WRONG` — по-английски |
| 429 | `RATE_LIMITED` | Код отдают два источника. Первый — собственный лимит операций, считается на портал, а не на ключ: 300 запросов в минуту у `crm/chats`, 120 — у `sessions/intercept` и `sessions/join`. Действующее значение берите из заголовка `X-RateLimit-Limit`, остаток и время сброса — из `X-RateLimit-Remaining` и `X-RateLimit-Reset`, они приходят с каждым ответом. Второй — Битрикс24, отбивший вызов по лимиту частоты: приходит заголовок `Retry-After` |
| 502 | `OPENLINE_SESSION_FAILED` | Битрикс24 ответил без подтверждения — `result` не `true`, при этом ошибку не вернул. Завершённость диалога такого ответа не даёт: вход и перехват на завершённом диалоге проходят успешно |
| 502 | `BITRIX_UNAVAILABLE` | Битрикс24 вернул ответ неожиданной формы |

Опечатка в `crmEntityType` отбивается до вызова Битрикс24 — ответом `400 INVALID_PARAMS` со списком допустимых значений.

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

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

- **Завершённость диалога не проверяется.** `sessions/intercept` и `sessions/join` проходят и на диалоге, сессия которого давно закрыта: оператор добавляется в участники чата, ответ — `intercepted: true` и `joined: true`. Хотите работать только с открытыми диалогами — берите `chatId` из `crm/chats` без `activeOnly=false`.
- **Повторный вход не ошибка.** `sessions/join` для оператора, который уже участвует в диалоге, снова отвечает `joined: true`.
- **Вход виден в списке участников.** После `join` оператор появляется среди участников чата открытой линии — это и есть проверка, что вызов подействовал.

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

- [Список сессий](./sessions.md)
- [Метаданные диалога](./dialog.md)
- [История сессии](./history.md)
- [Открытые линии](/docs/openlines)
