- Получите API ключ в кабинете WazzaBee → Коннекторы → API
- С вашего бэкенда отправьте POST запрос на
/v1/iframeс API ключом - Вставьте полученный URL в
<iframe>на вашей странице - Готово! Менеджер видит все чаты прямо в вашем приложении
Два варианта использования
| Вариант | scope | Где использовать |
|---|---|---|
| Общие чаты | global | Отдельная страница «Чаты» или «Мессенджеры» в меню вашего приложения |
| Чат клиента | card | Карточка клиента — показывает только переписку с этим клиентом |
POST /v1/iframe — встраивание чата WazzaBee
Этот эндпоинт позволяет встроить чат WazzaBee в вашу CRM-систему или любое веб-приложение через <iframe>. Идеально подходит для кастомных CRM на React, Vue, Angular или любом другом фреймворке.
- Ваш бэкенд запрашивает iframe-сессию через API
- API возвращает URL для встраивания
- Ваш фронтенд показывает
<iframe>с этим URL - Пользователь видит полноценный чат WazzaBee внутри вашего приложения
URL
POST https://api.wazzabee.com/api-gateway/v1/iframe
Заголовки
Authorization: Bearer ВАШ_API_КЛЮЧ
Content-Type: application/json
Параметры тела запроса
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
user | object | ✅ Да | Информация о пользователе вашей CRM |
user.id | string | ✅ Да | Идентификатор пользователя в вашей CRM-системе |
user.name | string | Нет | Имя пользователя (для отображения) |
scope | string | Нет | Режим отображения: global (все чаты) или card (чат конкретного контакта). По умолчанию: global |
filter | object | Условно | Фильтры для scope=card. Обязателен при scope=card |
filter.phone | string | — | Номер телефона контакта для фильтрации |
filter.channelIds | array | — | Ограничить показ определёнными каналами |
activeChat | object | Нет | Открыть конкретный чат сразу при загрузке |
options | object | Нет | Дополнительные настройки отображения |
Режимы отображения (scope)
global — все чаты
Показывает полный список диалогов, как в основном интерфейсе WazzaBee. Подходит для отдельной страницы «Чаты» в вашей CRM.
card — чат конкретного контакта
Фильтрует диалоги по телефону контакта. Идеально для встраивания в карточку клиента — менеджер видит только переписку с этим клиентом.
Доступные UI-действия в шапке списка диалогов
В iframe есть встроенный набор управляющих кнопок над списком чатов. Их видимость зависит от выбранного scope — UI автоматически адаптируется под сценарий менеджера в CRM:
| Действие | scope=global |
scope=card |
|---|---|---|
| 📌 Закрепить чат | ✅ | ✅ |
| 👁 Пометить непрочитанным | ✅ | ✅ |
| 📦 Архивировать чат + переключатель «активные / архив» | ✅ | ❌ скрыто |
| ✓✓ Прочитать все (в текущей линии / во всех линиях) | ✅ | ❌ скрыто |
| 🔄 Обновить список диалогов | ✅ | ❌ скрыто |
| ➕ Добавить контакт вручную | ✅ | ❌ скрыто — вместо этого автоматически открывается попап «Начать чат», если контакт по filter.phone ещё не существует |
| Отправка сообщений, медиа, голосовых, шаблонов | ✅ | ✅ |
card менеджер CRM работает с одним контактом — управляющие кнопки списка диалогов там не нужны и могут отвлекать. Поэтому они намеренно скрыты, чтобы UI был сфокусирован на переписке. В scope=global доступны все возможности основного кабинета WazzaBee.
Примеры запросов
Пример 1. Все чаты (scope=global)
curl -X POST "https://api.wazzabee.com/api-gateway/v1/iframe" \
-H "Authorization: Bearer ВАШ_API_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"user": {
"id": "manager-42",
"name": "Алексей Менеджер"
},
"scope": "global"
}'
Пример 2. Чат конкретного клиента (scope=card)
curl -X POST "https://api.wazzabee.com/api-gateway/v1/iframe" \
-H "Authorization: Bearer ВАШ_API_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"user": {
"id": "manager-42",
"name": "Алексей Менеджер"
},
"scope": "card",
"filter": {
"phone": "77001234567"
}
}'
Пример 3. С ограничением по каналам
curl -X POST "https://api.wazzabee.com/api-gateway/v1/iframe" \
-H "Authorization: Bearer ВАШ_API_КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{
"user": {
"id": "manager-42",
"name": "Алексей Менеджер"
},
"scope": "card",
"filter": {
"phone": "77001234567",
"channelIds": ["550e8400-e29b-41d4-a716-446655440000"]
}
}'
Успешный ответ (200 OK)
{
"success": true,
"url": "https://app.wazzabee.com/chat/embed/a1b2c3d4...64-символьный-токен",
"token": "a1b2c3d4...64-символьный-токен",
"expiresAt": "2026-03-13T10:00:00.000Z",
"scope": "card"
}
| Поле | Тип | Описание |
|---|---|---|
url | string | Готовый URL для вставки в <iframe src="..."> |
token | string | Токен сессии (64 символа hex) |
expiresAt | string (ISO 8601) | Время истечения сессии (24 часа от создания) |
scope | string | Выбранный режим: global или card |
Встраивание на фронтенде
Простой HTML
<iframe
src="https://app.wazzabee.com/chat/embed/ТОКЕН_СЕССИИ"
style="width: 100%; height: 600px; border: none;"
allow="clipboard-write"
></iframe>
React-компонент
import { useEffect, useState } from "react";
function WazzaBeeChat({ contactPhone }) {
const [iframeUrl, setIframeUrl] = useState(null);
useEffect(() => {
// Запрос к вашему бэкенду, который проксирует вызов к WazzaBee API
fetch("/api/wazzabee/iframe", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
phone: contactPhone,
scope: "card"
})
})
.then(res => res.json())
.then(data => setIframeUrl(data.url));
}, [contactPhone]);
if (!iframeUrl) return <div>Загрузка чата...</div>;
return (
<iframe
src={iframeUrl}
style={{ width: "100%", height: "600px", border: "none" }}
allow="clipboard-write"
/>
);
}
События postMessage
iframe отправляет события в родительское окно через window.postMessage. Вы можете слушать их для интеграции с вашей CRM.
event.data с полями source: "wazzabee", event: "WZ_..." и payload-полями. Проверяйте event.origin и event.data.source для безопасности.
Доступные события
| Событие | Когда срабатывает | Данные (поля payload) |
|---|---|---|
WZ_READY | Чат загрузился и готов к работе | { userId, scope } |
WZ_CHAT_OPENED | Менеджер открыл диалог или переключился на другой. Приходит при каждой смене активного чата — по нему обновляйте карточку клиента в своей CRM | { conversationId, chatId, phone, name, contactId, isGroup, contactPhone, contactName }⚠️ contactPhone, contactName — deprecated, используйте phone, name |
WZ_CHAT_CLOSED | Чат выгружен — пользователь ушёл со страницы с iframe. При переключении между диалогами не отправляется: смену активного чата ловите по WZ_CHAT_OPENED | {} |
WZ_MESSAGE_SENT | Менеджер отправил сообщение | { conversationId, chatId, phone, contactPhone } |
WZ_MESSAGE_RECEIVED | Получено новое сообщение (входящее или исходящее) | { messageId, conversationId, chatId, phone, direction, contentType, content, text, timestamp } |
WZ_MESSAGES_READ | Менеджер открыл чат (прочитал сообщения) | { conversationId, chatId, phone, contactPhone, unreadCount }⚠️ contactPhone — deprecated, используйте phone |
WZ_CREATE_CONTACT | Запрос на создание контакта в CRM | { phone, name } |
WZ_CHAT_NOT_FOUND | Запрошенный чат не найден (например, неверный телефон в scope=card) | { phone, reason } |
WZ_ACTION_NOT_SUPPORTED | Действие недоступно в текущем режиме (например, попытка переключиться вне scope=card) | { action, reason } |
WZ_UNREAD_TOTAL | Изменилась сумма непрочитанных — удобно для бейджа на вкладке CRM | { channelId, total }channelId = null, если к сессии привязано несколько линий связи |
WZ_SESSION_REFRESHED | Токен сессии продлён автоматически — реакции не требует | {} |
WZ_SESSION_EXPIRED | Сессия истекла — запросите новую ссылку на iframe | {} |
WZ_CONNECTION_LOST | Оборвалось realtime-соединение (сеть). Восстанавливается само, можно показать индикатор | { scope } |
phone и contactPhone: в событиях, связанных с контактом, мы шлём оба варианта — phone (рекомендуется) и устаревшее contactPhone. То же для name и contactName. Так интеграции не ломаются. В новых интеграциях используйте phone/name; устаревшие поля поддерживаются и удаляться не будут.
Пример обработки событий
window.addEventListener("message", (event) => {
// Проверяем источник
if (event.origin !== "https://app.wazzabee.com") return;
if (event.data?.source !== "wazzabee") return;
const { event: type, ...data } = event.data;
switch (type) {
case "WZ_READY":
console.log("Чат WazzaBee загружен, user:", data.userId, "scope:", data.scope);
break;
case "WZ_CHAT_OPENED":
// Рекомендуется: data.phone, data.name
console.log("Открыт диалог:", data.conversationId, "телефон:", data.phone);
// Можно обновить карточку клиента в CRM
break;
case "WZ_CHAT_CLOSED":
console.log("Диалог закрыт");
break;
case "WZ_MESSAGE_SENT":
console.log("Менеджер отправил сообщение в чат:", data.chatId, data.phone);
// Можно добавить запись в историю CRM
break;
case "WZ_MESSAGE_RECEIVED":
console.log("Новое сообщение:", data.content);
console.log("Направление:", data.direction);
break;
case "WZ_MESSAGES_READ":
console.log("Менеджер прочитал чат:", data.conversationId);
break;
case "WZ_CREATE_CONTACT":
console.log("Запрос на создание контакта:", data.phone, data.name);
// Можно автоматически создать контакт в вашей CRM
break;
case "WZ_CHAT_NOT_FOUND":
console.warn("Чат не найден:", data.phone, "причина:", data.reason);
// Например, предложить создать контакт
break;
case "WZ_ACTION_NOT_SUPPORTED":
console.warn("Действие недоступно:", data.action, "причина:", data.reason);
break;
}
});
Управление чатом из вашей CRM
Обмен двусторонний: не только iframe сообщает вам о происходящем, но и вы можете управлять им. Отправьте в iframe postMessage с полем source: "crm".
| Action | Данные | Поведение |
|---|---|---|
OPEN_CHAT_BY_PHONE | { phone } | Открыть чат с этим номером. В ответ придёт WZ_CHAT_OPENED (нашли) или WZ_CHAT_NOT_FOUND (нет такого контакта). В режиме scope=card вернётся WZ_ACTION_NOT_SUPPORTED |
Номер нормализуется по цифрам — формат любой: +7 (700) 123-45-67, 77001234567, 87001234567 сработают одинаково.
iframeRef.current?.contentWindow?.postMessage({
source: "crm",
action: "OPEN_CHAT_BY_PHONE",
phone: "+77001234567",
}, "*");
Сценарий: карточка клиента слева, чат справа
Типовая задача при встраивании в CRM: справа менеджер ведёт переписку, слева — карточка клиента, каталог товаров, кнопки действий. Когда менеджер переключается на другой чат, левая часть должна сама подтянуть данные нового собеседника.
WZ_CHAT_OPENED — достаточно подписаться на message в родительском окне.
const [activeChat, setActiveChat] = useState(null);
useEffect(() => {
const handler = (event) => {
if (event.origin !== "https://app.wazzabee.com") return;
if (event.data?.source !== "wazzabee") return;
// Менеджер переключился на другой чат
if (event.data.event === "WZ_CHAT_OPENED") {
setActiveChat({
chatId: event.data.chatId,
phone: event.data.phone,
name: event.data.name,
});
// Тянем карточку клиента по номеру из своей CRM
loadCustomerCard(event.data.phone);
}
};
window.addEventListener("message", handler);
return () => window.removeEventListener("message", handler);
}, []);
Обратный ход — менеджер открыл сделку в CRM и хочет сразу перейти к переписке: пошлите в iframe OPEN_CHAT_BY_PHONE, и чат сам переключится на нужный диалог.
Возможные ошибки
| Код | Ошибка | Причина |
|---|---|---|
400 | Поле user.id обязательно | Не передан идентификатор пользователя CRM |
400 | Для scope=card необходимо указать filter | Выбран режим card, но не указан фильтр |
Время жизни сессии
- Сессия действует 24 часа с момента создания
- После истечения iframe покажет ошибку — нужно запросить новый токен
- Рекомендуем обновлять токен заранее (например, каждые 12 часов)
- Для каждого пользователя CRM создаётся отдельная сессия
Кто из менеджеров ответил клиенту
Имя, которое вы передаёте в user.name при создании сессии, — это автор сообщений. Под каждым исходящим сообщением в ленте чата видна подпись вида «из WazzaBee · Назерке А.»: так по переписке понятно, кто из менеджеров ответил. Фамилия сокращается до инициала.
Подпись работает для всего, что оператор отправляет из встроенного чата: текста, файлов, голосовых и WABA-шаблонов.
Что нужно передавать
| Поле | Зачем |
|---|---|
user.name | Имя сотрудника — попадает в подпись под сообщением и в вебхук messages_outgoing (author.name) |
user.id | Идентификатор сотрудника в вашей CRM — возвращаем его в вебхуке как author.userId, чтобы вы сопоставили ответ со своим менеджером |
