Встраивание чата AISAR
Как встроить полнофункциональный чат AISAR в стороннее приложение через iframe: авторизация, три режима отображения, полный сценарий интеграции.
AISAR предоставляет встраиваемый чат (embed chat) — полнофункциональный мессенджер, загружаемый в <iframe> на стороне вашего приложения. Пользователь работает с чатом внутри вашего UI, не покидая его.
Архитектура
Ваше приложение (бэкенд)
│
├─ 1. Создать API-токен (однократно, через AISAR UI)
├─ 2. Получить список юзеров GET /v1/users
├─ 3. Найти контакт по телефону GET /v1/contacts/lookup?q=...
├─ 4. Получить список каналов GET /v1/channels
├─ 5. Отправить сообщение POST /v1/messages/send
│
├─ 6. Авторизовать юзера POST /v1/embed/auth
│ → получить session token
│
└─ 7. Открыть iframe
https://my.aisar.app/embed/chat?token=<session_token>&...Шаги 2–3 кэшируются на вашей стороне. Шаг 4 выполняется при каждом открытии iframe (токен живёт 8 часов). Все API-запросы используют базовый URL https://api.aisar.app с префиксом /v1 и заголовок Authorization: Bearer <api_token>, выданный один раз в интерфейсе AISAR (Настройки → API-токены; раздел доступен компаниям на бизнес-тарифе с включённой функцией API). Партнёр получает ключ при подключении компании.
Эндпоинты
Список пользователей
Возвращает всех реальных пользователей компании (не сервисные аккаунты) — используйте для сопоставления ваших пользователей с пользователями AISAR.
GET /v1/users
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json{
"data": [
{
"id": 1,
"name": "Алексей",
"lastname": "Петров",
"email": "alexey@company.kz",
"availability": "online",
"last_login_at": "2026-03-15T10:30:00.000000Z"
}
]
}id (используется в embed/auth), name, lastname, email, availability (online/offline/away).
Поиск контактов
Поиск по номеру телефона, внешнему ID или username. Результат даёт contact_id, который используется в iframe URL (режим 3).
GET /v1/contacts/lookup?q=<query>
Authorization: Bearer YOUR_API_TOKEN
Accept: application/jsonq (обязателен, строка 2–255 символов) ищет по номеру телефона (+12025550187), external ID аккаунта (12025550187@s.whatsapp.net) и username (alexey_petrov), нечёткое совпадение (ILIKE). Ограничение: максимум 20 результатов, группы и объединённые контакты исключаются.
{
"data": [
{
"id": 42,
"company_id": 1,
"firstName": "Алексей",
"lastName": "Петров",
"displayName": "Алексей Петров",
"status": "active",
"phones": [{ "phone": "+12025550187", "type": "mobile" }],
"contactAccounts": [
{ "id": 10, "account_type": "whatsapp", "external_id": "+12025550187", "is_group": false }
],
"tags": []
}
]
}Список каналов
Возвращает каналы компании, доступные текущему пользователю — для получения channel_id, нужного при отправке сообщений.
GET /v1/channels
Authorization: Bearer YOUR_API_TOKEN
Accept: application/jsonQuery-параметры (все опциональны): type (тип канала), status (active/inactive), channel_type_id, setup_state, include_setup_drafts (по умолчанию false).
Отправить сообщение
Отправляет исходящее текстовое сообщение контакту через указанный канал; если диалог отсутствует — создаётся автоматически.
POST /v1/messages/send
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
Content-Type: application/json
{
"channel_id": 3,
"recipient": "+12025550187",
"message_content": "Здравствуйте! Ваш заказ готов."
}channel_id (обязательно, из GET /v1/channels), recipient (обязательно, номер телефона или external_id получателя, формат зависит от типа канала), message_content (обязательно, максимум 65 535 символов). Ответ 200: { "success": true }. Полный справочник этого эндпоинта (вложения, голосовые, группы WhatsApp, шаблоны) — в гайде «Отправка сообщений: справочник эндпоинтов».
Авторизация для embed
Создаёт короткоживущий session-токен для конкретного пользователя — этот токен передаётся в URL iframe.
POST /v1/embed/auth
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
Content-Type: application/json
{
"user_id": 1
}{
"token": "YOUR_EMBED_SESSION_TOKEN",
"redirect_url": "https://my.aisar.app/embed/chat"
}user_id обязан принадлежать реальному пользователю той же компании, что и API-токен — сервисные аккаунты и администраторы платформы не допускаются. token живёт 8 часов. Ошибки: 400 — отсутствует user_id; 403 — вызов не полным API-токеном компании, а узким токеном её служебного аккаунта (например, токеном встроенного чата), error: "This token cannot issue embed sessions"; 422 — пользователь не найден в компании. С 2026-09-28 выданный токен привязан к компании, которая его выпустила: запросы с ним всегда выполняются в этой компании, какая бы компания ни была у пользователя текущей; на платформенных эндпоинтах он не действует (403), а PUT /v1/me/current-company на другую компанию отвечает 403 с error: "token_company_bound". Если пользователь перестал состоять в компании, уже выданный токен тоже перестаёт работать (403).Выданный session-токен имеет ограниченный scope embed:read и живёт 8 часов — этого достаточно для работы встроенного чата, но он не заменяет полноценный API-токен.
Отдельные эндпоинты отказывают embed-токену явно — 403, независимо от того, что именно перечислено в scope. Сейчас так закрыты: сводная аналитика компании (дашборд — выручка, сделки, объёмы диалогов и сообщений, нагрузка по операторам), поиск по расшифровкам звонков (q_in=transcript|all в GET /v1/calls) и очередь перезвона по пропущенным (/v1/telephony/callbacks*). Общее правило: если поверхность отдаёт коммерческую сводку по всей компании или пакетную выгрузку персональных данных, встроенному в чужой интерфейс токену она недоступна — обращайтесь к ней со своего бэкенда обычным API-токеном.
Авторизация из CRM (Bitrix24 и другие)
Альтернативный режим POST /v1/embed/auth — для встраивания чата прямо из интерфейса CRM (например, из карточки в Bitrix24), когда запрос инициирует установленное в CRM приложение, а не ваш бэкенд с API-токеном. Вместо user_id передаётся идентификатор портала CRM.
POST /v1/embed/auth
Accept: application/json
Content-Type: application/json
{
"type": "bitrix24",
"member_id": "YOUR_CRM_MEMBER_ID",
"payload": {
"AUTH_ID": "PORTAL_ISSUED_ACCESS_TOKEN"
}
}type (обязательно, тип CRM: bitrix24 и др.), member_id (обязательно, идентификатор портала CRM), payload (обязательно объект — иначе 400). Для bitrix24 поле payload.AUTH_ID обязательно и обязано быть строкой (иначе 400): это access-токен, которым личность вызывающего проверяется прямым запросом к порталу (user.current). Ответ — тот же конверт { "token": ..., "redirect_url": ... }, что и в режиме с user_id; токен также имеет scope embed:read и живёт 8 часов.
AUTH_ID, с невалидным AUTH_ID, либо если проверенный CRM-пользователь не замаплен на пользователя AISAR или больше не состоит в компании — 422, токен не выдаётся. Фолбэка на «первого пользователя компании» больше нет: пустой или отсутствующий payload.AUTH_ID раньше молча выдавал такой токен, сейчас — только отказ. Если в payload передан b24_user_id, он игнорируется: личность нельзя назвать с провода, она подтверждается только верификацией AUTH_ID на портале.POST /v1/embed/auth ограничен по частоте на весь маршрут: вызовы с Bearer-токеном сервисного аккаунта (режим с user_id) — до 120 запросов в минуту на токен; анонимные вызовы этого CRM-режима — до 30 запросов в минуту на IP.
Встраивание iframe
Где можно встраивать и атрибуты iframe
С 2026-10-08 встроенный чат https://my.aisar.app/embed/chat?token=... можно встраивать в <iframe> на любом сайте по https — регистрировать домен в AISAR не нужно. Без токена в адресе страница не встраивается. Токен выдаёт сервер интегратора: POST /v1/embed/auth с ключом API сервисного аккаунта компании (в кабинете: Настройки, API-токены) и user_id сотрудника. Токен привязан к этому сотруднику и компании, даёт права только на работу встроенного чата и живёт 8 часов; держите его на сервере, не пишите в логи, а после загрузки страница сама убирает токен из адреса.
Рекомендуемые атрибуты iframe: allow="microphone; clipboard-write" (голосовые сообщения, звонки из встроенного чата и копирование в буфер). Атрибут sandbox лучше не ставить; если он нужен, разрешите allow-scripts allow-same-origin allow-popups allow-forms allow-downloads.
<iframe
src="https://my.aisar.app/embed/chat?token=<session_token>"
allow="microphone; clipboard-write"
style="width: 100%; height: 100%; border: none;"
></iframe>Три режима отображения
Режим 1 — полный чат (inbox). Полнофункциональный мессенджер со списком диалогов, фильтрами, поиском и панелью сообщений.
<iframe
src="https://my.aisar.app/embed/chat?token=<session_token>"
style="width: 100%; height: 100%; border: none;"
></iframe>Режим 2 — чат с предзаполненным поиском. Тот же полный чат, но строка поиска сразу заполнена (параметр search).
<iframe
src="https://my.aisar.app/embed/chat?token=<session_token>&search=+12025550187"
style="width: 100%; height: 100%; border: none;"
></iframe>Режим 3 — панель сообщений контакта. Только панель сообщений для конкретного контакта, без списка диалогов и фильтров — идеально для встраивания в карточку клиента. Параметры: contact_id (из /v1/contacts/lookup), view=messages. Поведение: загружает последний диалог контакта; если диалогов нет — показывает пустое состояние; панель полнофункциональна (отправка/редактирование сообщений, управление диалогом).
<iframe
src="https://my.aisar.app/embed/chat?token=<session_token>&contact_id=42&view=messages"
style="width: 100%; height: 100%; border: none;"
></iframe>Дополнительные параметры
| Параметр | Описание |
|---|---|
lang | Язык интерфейса: en, ru, kk. По умолчанию ru |
contact_id | ID контакта (без view=messages — фильтрует список диалогов) |
deal_id | ID сделки — открывает чат в контексте конкретной сделки |
Полный пример интеграции (Python)
API_TOKEN = "YOUR_API_TOKEN"
API_BASE = "https://api.aisar.app/v1"
EMBED_BASE = "https://my.aisar.app/embed/chat"
headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Accept": "application/json",
}
# Получите список пользователей для маппинга
response = requests.get(f"{API_BASE}/users", headers=headers)
aisar_users = response.json()["data"]
user_mapping = {
"your_user_123": 1, # Алексей → AISAR user ID 1
"your_user_456": 2, # Мария → AISAR user ID 2
}
# Найдите контакты по телефонам (кэшируйте результат)
response = requests.get(
f"{API_BASE}/contacts/lookup",
params={"q": "+12025550187"},
headers=headers,
)
contacts = response.json()["data"] # contacts[0]["id"] = 42 ← contact_id для iframeaisar_user_id = user_mapping["your_user_123"]
response = requests.post(
f"{API_BASE}/embed/auth",
json={"user_id": aisar_user_id},
headers=headers,
)
session_token = response.json()["token"]
# Режим 1: полный чат
iframe_url = f"{EMBED_BASE}?token={session_token}"
# Режим 2: предзаполненный поиск
iframe_url = f"{EMBED_BASE}?token={session_token}&search=+12025550187"
# Режим 3: панель сообщений контакта
iframe_url = f"{EMBED_BASE}?token={session_token}&contact_id=42&view=messages"Рекомендации
Кэширование
| Что | Как часто обновлять |
|---|---|
| API-токен | Постоянный (пока не отозван) |
| Список пользователей | При изменении состава команды |
| Маппинг контактов | При первом обращении + по мере необходимости |
| Session token | Каждый раз при открытии iframe (живёт 8 часов) |
Размеры iframe
| Режим | Рекомендуемый размер |
|---|---|
| Полный чат (1, 2) | min-width: 800px, min-height: 600px |
| Панель сообщений (3) | min-width: 400px, min-height: 500px |
Безопасность
- Никогда не передавайте API-токен на фронтенд. Авторизация (
/v1/embed/auth) должна происходить на вашем бэкенде. - Session-токен передаётся через URL — iframe очищает его из адресной строки сразу после загрузки.
- Токен в адресе iframe не должен попадать в логи вашего сервера и аналитику: держите его только в памяти страницы и выдавайте на каждое открытие.
- Session-токен имеет ограниченные права и срок жизни 8 часов.
Обработка ошибок
| Код | Причина | Действие |
|---|---|---|
| 401 | Невалидный/истекший API-токен | Проверьте API-токен в настройках AISAR |
| 400 | Отсутствует обязательный параметр | Проверьте user_id в embed/auth |
| 422 | Пользователь/контакт не найден | Проверьте ID и принадлежность к компании |
Ограничения
- Один API-токен = одна компания. Для нескольких компаний — отдельные токены.
contact_idотносится к компании API-токена — контакты других компаний недоступны.- Iframe работает только с HTTPS (кроме localhost).
- Максимум 20 результатов в
/v1/contacts/lookup.