CRM-бот в MAX — это не «бот с формой». Это автоматизированная воронка продаж, которая принимает входящие заявки в российском мессенджере, квалифицирует их, передаёт в основную CRM, ставит задачи менеджерам, шлёт двусторонние уведомления и возвращается к клиенту с напоминаниями. Если лиды из MAX не попадают в CRM, отдел продаж работает вслепую: менеджер забывает перезвонить, маркетинг не видит реальную конверсию по UTM, руководитель не понимает, какой канал окупается. Разберём, как такой бот устроен изнутри: архитектура, российские CRM, примеры кода для amoCRM и Битрикс24, идентификация клиента, очередь интеграций для надёжности и сквозная аналитика до выручки.
Зачем интегрировать MAX-бота с CRM
Польза от связки бот-в-MAX + CRM сводится к пяти вещам, и каждая из них напрямую конвертируется в деньги.
- Единая база лидов. Все обращения — из MAX-бота, с сайта, с email-рассылок, из звонков, из Telegram — в одной точке. Менеджер не открывает шесть вкладок, чтобы понять, кто этот человек и о чём с ним договорились в прошлый раз.
- Авто-распределение. Лид попал в CRM — система сама присвоила ответственного по правилам (по региону, продукту, нагрузке менеджеров, времени суток). Никто вручную не «расхватывает» горячие заявки и не теряет холодные.
- История коммуникаций. В карточке клиента видно, что он спрашивал в MAX-боте полгода назад, какую услугу выбирал, какие возражения снимал менеджер. Передача между сотрудниками не теряет контекст.
- Сквозная аналитика. UTM-метка из бота тянется в сделку, сделка — в выручку. Видно, какой источник трафика реально продаёт, а не только генерирует лиды.
- Меньше ручной работы. Менеджеру не нужно копировать телефон, имя, текст обращения из MAX-чата в карточку CRM. Автоматика делает это за миллисекунды и без опечаток.
Если хотя бы один из этих пунктов закрывается с трудом — пора интегрировать.
Базовые сценарии автоматизации
Минимальный набор сценариев, ради которых это всё затевается. Каждый по отдельности экономит 1–3 минуты на лиде; на потоке в 200 лидов в месяц это 5–10 часов рабочего времени и существенно меньшая просадка по конверсии.
- Новый лид → создать сделку. Пользователь оставил заявку в MAX-боте — в CRM появилась сделка с контактом, источником, UTM, ответственным.
- Ответ клиента в боте → обновить статус. Клиент нажал «Готов обсуждать» — сделка двинулась по воронке. Ушёл в молчание на 3 дня — задача менеджеру «реактивировать».
- Сделка закрыта → отправить NPS. Через 7 дней после статуса «Оплачено» бот сам спрашивает: «Оцените от 1 до 10». Ответы складываются в кастом-поле сделки.
- Забытый лид → реактивация через бот. Сделка висит без активности 14 дней — CRM шлёт webhook, MAX-бот мягко напоминает клиенту: «Остались вопросы?».
- Эскалация на оператора. Бот не понял запрос — ставит задачу менеджеру в CRM с прямой ссылкой на чат в MAX.
- Уведомления менеджеру. Новая горячая сделка — менеджер получает в личный MAX сообщение от служебного бота с кнопкой «Открыть в CRM».
Всё это — обычные, проверенные сценарии. Никакой магии, только аккуратная автоматизация рутинных шагов.
Архитектура
Минимально жизнеспособный CRM-бот в MAX выглядит так:
- Frontend (бот в MAX). Сценарий диалога, FSM (finite state machine), валидация ввода, инлайн-клавиатуры с быстрыми ответами.
- Backend. Сервис заявок, очередь интеграций (брокер сообщений), обработчик webhook от CRM, сервис уведомлений.
- CRM-адаптер. Тонкий слой, инкапсулирующий API конкретной CRM (amoCRM, Битрикс24, Мегаплан, RetailCRM). Интерфейс с методами
createDeal,updateDeal,addNote,findContact. Реализация под конкретную CRM скрыта за интерфейсом. - Уведомления. Отдельный воркер для рассылки менеджерам и клиентам, чтобы основной поток обработки не блокировался отправкой сообщений.
Адаптер — обязательно отдельный модуль, потому что CRM могут меняться. Сегодня amoCRM, завтра Битрикс24 — основной код не должен переписываться. При смене CRM меняется только реализация адаптера, и это занимает 1–2 недели против 4–6 недель полной переработки, если интеграция была «зашита» в обработчики бота напрямую.
Поток данных в системе:
MAX-бот → очередь (RabbitMQ) → CRM-адаптер → amoCRM / Битрикс24
↑ ↓
└────── retry ────────┘
↓
Dead Letter Queue (раз в день дежурный)
CRM-webhook → обработчик webhook → MAX-бот (уведомление клиенту/менеджеру)
Сценарий квалификации
Хороший CRM-бот не задаёт 20 вопросов подряд. Логика обычно такая:
- 2–3 ключевых вопроса для отсева нецелевых лидов (бюджет, регион, цель обращения).
- Если лид нецелевой — мягкий отказ с переадресацией в FAQ или базу знаний.
- Если целевой — детальные вопросы и фиксация полной заявки в БД.
- Параллельно бот собирает «технические» данные: UTM-метки, referrer, время суток, устройство.
Каждое поле сохраняется сразу в БД, чтобы при обрыве диалога не потерять то, что уже введено. Передача в CRM идёт только после полной квалификации, а не по первому касанию — иначе CRM забивается мусорными карточками и менеджеры перестают доверять каналу.
Российские CRM: краткий обзор
Рынок РФ в 2026 году достаточно консолидированный — большинство задач закрывают 4–5 систем.
amoCRM — самый популярный выбор для услуг и B2C. REST API на OAuth 2.0, понятная документация, цифровая воронка с автоматизацией, виджеты в карточке, встроенный мессенджер-канал (можно завести MAX-бот как источник через Chat API). Лимит — 7 запросов в секунду на аккаунт.
Битрикс24 — тяжеловес для B2B и крупных компаний. REST + входящие/исходящие webhooks, OpenLine как канал для чатов (поддерживает кастом-коннекторы для нестандартных мессенджеров вроде MAX), мощные права и бизнес-процессы, но порог входа высокий. Лимиты гибкие, зависят от тарифа.
Мегаплан — нишевый, но живой. Удобен в проектных продажах. REST API, webhooks по событиям. Менее активное комьюнити по сравнению с amoCRM/Битриксом, документация скромнее.
RetailCRM — стандарт для интернет-магазинов и retail. Интеграции с 1С, эквайрингами, маркетплейсами. MAX-бот тут создаёт не сделку, а заказ напрямую с составом корзины и параметрами доставки.
Сравнительная таблица
| CRM | Auth | Rate limits | Webhooks | Стоимость интеграции |
|---|---|---|---|---|
| amoCRM | OAuth 2.0 | 7 RPS | Входящие + исходящие | 50–150 тыс ₽ |
| Битрикс24 | OAuth 2.0 / вебхук-токен | 2 RPS на метод | Входящие + исходящие | 80–250 тыс ₽ |
| Мегаплан | API key | 10 RPS | Только входящие в МП | 60–180 тыс ₽ |
| RetailCRM | API key | 300 запросов/мин | Триггеры + webhooks | 80–200 тыс ₽ |
Цифры — ориентир для типового проекта «создание сделки + двусторонняя синхронизация статусов + UTM». Глубокая интеграция с кастомными воронками, OpenLine-коннектором и виджетами в UI обычно дороже на 50–100%.
amoCRM: примеры кода
Самый частый стек у нас — Python + httpx. Создание контакта и сделки в amoCRM из MAX-бота выглядит так:
import httpx
AMO_BASE = "https://example.amocrm.ru/api/v4"
HEADERS = {"Authorization": f"Bearer {ACCESS_TOKEN}"}
async def create_lead_amo(client: httpx.AsyncClient, lead: dict) -> int:
# 1. Создаём контакт
contact_payload = [{
"name": lead["name"],
"custom_fields_values": [
{"field_code": "PHONE", "values": [{"value": lead["phone"], "enum_code": "MOB"}]},
{"field_code": "EMAIL", "values": [{"value": lead["email"], "enum_code": "WORK"}]},
],
}]
r = await client.post(f"{AMO_BASE}/contacts", json=contact_payload, headers=HEADERS)
r.raise_for_status()
contact_id = r.json()["_embedded"]["contacts"][0]["id"]
# 2. Создаём сделку с привязкой к контакту, тегами, UTM в кастом-поле
deal_payload = [{
"name": f"Заявка из MAX: {lead['name']}",
"price": lead.get("budget", 0),
"pipeline_id": 1234567,
"status_id": 7654321, # «Первичный контакт»
"responsible_user_id": 111, # Авто-распределение по правилу
"_embedded": {
"contacts": [{"id": contact_id}],
"tags": [{"name": "max_bot"}, {"name": lead["utm_source"]}],
},
"custom_fields_values": [
{"field_id": 555001, "values": [{"value": lead["utm_source"]}]},
{"field_id": 555002, "values": [{"value": lead["utm_campaign"]}]},
{"field_id": 555003, "values": [{"value": str(lead["max_user_id"])}]},
],
}]
r = await client.post(f"{AMO_BASE}/leads", json=deal_payload, headers=HEADERS)
r.raise_for_status()
return r.json()["_embedded"]["leads"][0]["id"]
Обратите внимание на field_code против field_id: код используется для системных полей (PHONE, EMAIL), а ID — для кастомных. ID берутся из настроек аккаунта /api/v4/leads/custom_fields. Поле max_user_id критично — по нему мы потом найдём клиента при повторном обращении без необходимости снова просить телефон.
Битрикс24: REST и OpenLine
Битрикс попроще для старта — есть «входящий вебхук» (статичный URL с токеном), который не требует OAuth-флоу:
import httpx
BX_HOOK = "https://example.bitrix24.ru/rest/1/abc123def456/"
async def create_deal_bx(client: httpx.AsyncClient, lead: dict) -> int:
# Сначала ищем контакт по телефону
r = await client.post(f"{BX_HOOK}crm.contact.list", json={
"filter": {"PHONE": lead["phone"]},
"select": ["ID"],
})
contacts = r.json().get("result", [])
contact_id = contacts[0]["ID"] if contacts else None
if not contact_id:
r = await client.post(f"{BX_HOOK}crm.contact.add", json={
"fields": {
"NAME": lead["name"],
"PHONE": [{"VALUE": lead["phone"], "VALUE_TYPE": "MOBILE"}],
"SOURCE_ID": "MAX_MESSENGER",
},
})
contact_id = r.json()["result"]
r = await client.post(f"{BX_HOOK}crm.deal.add", json={
"fields": {
"TITLE": f"MAX: {lead['name']}",
"CONTACT_ID": contact_id,
"CATEGORY_ID": 0,
"STAGE_ID": "NEW",
"ASSIGNED_BY_ID": lead.get("manager_id", 1),
"UF_CRM_MAX_USER_ID": str(lead["max_user_id"]),
"UF_CRM_UTM_SOURCE": lead.get("utm_source", ""),
},
})
return r.json()["result"]
OpenLine («Открытые линии») — отдельная история. Это канал, через который сообщения из MAX-бота попадают в чат-карточку клиента в Битриксе, а ответы менеджера автоматически уходят клиенту обратно в MAX. Подключение делается через REST-методы imopenlines.network.join + imconnector.activate с реализацией кастомного коннектора для протокола MAX. Это путь для двусторонней переписки без написания собственного middleware.
Двусторонняя синхронизация
Самое ценное — когда клиент пишет в MAX-бот, а менеджер видит сообщение в карточке CRM и отвечает оттуда же. Архитектурно есть два пути.
- Через готовый канал (amoCRM Chat API, Битрикс OpenLine). CRM сама держит UI чата, бот выступает «коннектором»: получает сообщения из CRM по webhook и шлёт в MAX, и наоборот. Простой и быстрый путь.
- Через свой middleware. Бот пишет историю сообщений в собственную БД, в карточку CRM кладёт только ссылку «Открыть переписку». Менеджер кликает — открывается мини-веб-интерфейс с чатом. Гибче, но дороже в разработке.
Первый путь подходит, когда команда уже живёт в CRM и не хочет лишних инструментов. Второй — когда нужна нестандартная UX (шаблоны, быстрые ответы, AI-suggest, метки настроения клиента, голосовые расшифровки).
Идентификация клиента
Главный вопрос: как связать max user_id с контактом в CRM? У клиента может не быть телефона в профиле MAX, а может быть несколько аккаунтов (личный и рабочий). Стратегии в порядке убывания надёжности:
- По верифицированному телефону. MAX-бот просит поделиться контактом — мессенджер возвращает номер, привязанный к аккаунту. Этому номеру можно доверять.
- По email. Менее надёжно — клиент может ввести чужой. Полезно, если CRM первична для email-маркетинга.
- По кастом-полю
max_user_id. Сохраняем ID MAX-пользователя в отдельное поле контакта при первом обращении. На повторных обращениях находим клиента за один запрос. - По deeplink с параметром. В рассылке менеджер шлёт ссылку с payload — бот при
/startпонимает, что это лид из CRM, и сразу его идентифицирует.
Хорошая практика — комбинировать. При первом контакте просим телефон, сохраняем max_user_id в кастом-поле, дальше работаем по нему.
Безопасность токенов и доступов
CRM-токен с правами на запись — это ключ от всей базы клиентов. Утечка равна катастрофе.
- Только в env (
.env, secrets manager, Vault). Никогда в репозиторий. - Регулярная ротация — раз в 90 дней меняем токены, OAuth refresh обновляем по расписанию.
- Минимальные scopes. В amoCRM/Битриксе можно создать вебхук с правами только на нужные методы — не давайте полный доступ, если нужен только
crm.deal.add. - IP-allowlist на стороне CRM, если поддерживается. Битрикс это умеет.
- Аудит-лог. Все запросы к CRM логируем со стороны бота — кто, когда, что записал. При компрометации можно понять масштаб инцидента.
Очередь интеграций для надёжности
CRM может упасть, провести регламентные работы, получить таймаут на 30 секунд — а лиды поступать продолжают. Если MAX-бот пишет в CRM напрямую и синхронно, потеря лидов гарантирована при первом же сбое.
Решение — брокер сообщений между ботом и CRM-коннектором:
# Producer: бот при получении заявки кладёт её в очередь
async def on_lead_received(lead: dict):
await rabbitmq.publish(
exchange="crm",
routing_key="lead.new",
body=json.dumps(lead).encode(),
headers={"x-retry-count": "0"},
)
# Consumer: отдельный воркер достаёт и шлёт в CRM
async def consume_leads():
async for msg in rabbitmq.consume("crm.lead.new"):
try:
await create_lead_amo(http_client, json.loads(msg.body))
await msg.ack()
except RetryableError as e:
await retry_or_dlq(msg, e)
Подходит RabbitMQ, NATS, Redis Streams. Главное — два требования: персистентность (сообщения переживают рестарт брокера) и подтверждение доставки (ack только после успешной записи в CRM).
Webhook от CRM в MAX-бот
Обратное направление: CRM сообщает боту о событиях. Битрикс шлёт POST на наш эндпоинт при изменении сделки:
from fastapi import FastAPI, Request, HTTPException
import hmac, hashlib
app = FastAPI()
@app.post("/webhook/bx/deal-update")
async def bx_deal_update(request: Request):
# 1. Проверяем подпись (если включена)
body = await request.body()
signature = request.headers.get("X-Bitrix-Signature", "")
expected = hmac.new(WEBHOOK_SECRET.encode(), body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, expected):
raise HTTPException(403, "bad signature")
payload = await request.form()
event = payload.get("event")
deal_id = payload.get("data[FIELDS][ID]")
if event == "ONCRMDEALUPDATE":
deal = await fetch_deal(deal_id)
max_user_id = deal.get("UF_CRM_MAX_USER_ID")
new_stage = deal["STAGE_ID"]
# 2. Уведомляем клиента в MAX-боте о смене статуса
if max_user_id and new_stage in NOTIFY_STAGES:
await max_bot.send_message(
int(max_user_id),
STAGE_TEMPLATES[new_stage].format(deal_id=deal_id),
)
# 3. Уведомляем ответственного менеджера в служебном MAX-боте
manager_max = await get_manager_max(deal["ASSIGNED_BY_ID"])
if manager_max:
await staff_bot.send_message(
manager_max,
f"Сделка #{deal_id} перешла в «{new_stage}»",
)
return {"ok": True}
Сценарии «менеджеру в личный MAX» особенно ценят руководители — не нужно держать вкладку с CRM открытой весь день, чтобы вовремя реагировать на горячие сделки.
Обработка ошибок и ретраи
API любой CRM иногда отвечает плохо. Шаблон обработки:
- 401/403 — токен протух или прав не хватает. Останавливаем воркер, шлём алерт DevOps. Ретраить бессмысленно.
- 404 — объект удалён в CRM. Помечаем сообщение как «не доставлено», в DLQ. Часто это нормально (клиент удалил тестовую сделку).
- 429 — превысили rate limit. Ретраим с exponential backoff и jitter, уважаем
Retry-Afterесли заголовок есть. - 5xx — временная проблема CRM. Ретраим 3–5 раз с backoff, потом в DLQ.
- Сетевые таймауты — то же, что 5xx.
Простой helper для ретраев:
import asyncio, random, httpx
from typing import Awaitable, Callable, TypeVar
T = TypeVar("T")
async def with_retry(
fn: Callable[[], Awaitable[T]],
*,
max_attempts: int = 5,
base_delay: float = 0.5,
max_delay: float = 30.0,
) -> T:
for attempt in range(1, max_attempts + 1):
try:
return await fn()
except httpx.HTTPStatusError as e:
status = e.response.status_code
if status in (401, 403, 404):
raise # бессмысленно ретраить
if status == 429:
retry_after = float(e.response.headers.get("Retry-After", base_delay))
await asyncio.sleep(retry_after)
continue
if attempt == max_attempts or status < 500:
raise
except (httpx.TimeoutException, httpx.NetworkError):
if attempt == max_attempts:
raise
delay = min(max_delay, base_delay * 2 ** (attempt - 1))
delay += random.uniform(0, delay * 0.25) # jitter
await asyncio.sleep(delay)
raise RuntimeError("unreachable")
Сообщения, упавшие после всех ретраев, складываем в Dead Letter Queue — отдельный топик/очередь, которую раз в день просматривает дежурный.
# Dead Letter Queue: сохраняем "сломанные" сообщения для разбора
async def retry_or_dlq(msg, exc: Exception):
retries = int(msg.headers.get("x-retry-count", 0))
if retries < MAX_RETRIES and is_retryable(exc):
await rabbitmq.publish(
exchange="crm",
routing_key="lead.new",
body=msg.body,
headers={"x-retry-count": str(retries + 1)},
delay_ms=backoff_delay(retries),
)
await msg.ack()
else:
# В DLQ кладём оригинал + причину + traceback
await rabbitmq.publish(
exchange="crm.dlq",
routing_key="lead.failed",
body=msg.body,
headers={
"x-original-error": str(exc)[:500],
"x-failed-at": datetime.utcnow().isoformat(),
"x-retries": str(retries),
},
)
await msg.ack()
await alert_devops(f"Лид в DLQ: {exc}")
Дежурный раз в день открывает DLQ, разбирает по причинам (недоступная CRM, кривое поле, удалённая воронка), руками или скриптом перекладывает обратно. Лиды не теряются.
SaaS-конструкторы vs кастом
Альтернатива — собрать интеграцию без кода через визуальный конструктор:
- n8n — open-source, self-hosted или cloud. Сотни готовых нод, можно подключить MAX-бот через generic HTTP node + amoCRM/Битрикс из коробки. Подходит, когда логика умещается в DAG из 5–15 шагов.
- Albato — российский SaaS, заточен под РФ-сервисы (amoCRM, МойСклад, ЮKassa, Wildberries). Работает быстро, поддержка отвечает на русском.
Когда конструктор — норм:
- Бизнес-логика простая, без сложных условий и циклов.
- Объём — до 10 000 сделок/месяц (дальше дорого по подписке).
- Команда не хочет содержать инфраструктуру.
Когда нужен кастом:
- Нестандартные сценарии (например, AI-анализ диалога перед записью в CRM).
- Высокая нагрузка (сотни тысяч сделок).
- Жёсткие требования по безопасности (изолированный контур, нет права слать данные в облако).
- Двусторонняя синхронизация переписки с богатой UX.
Часто оптимален гибрид: критичный путь «лид → сделка» делаем кастомом, а вспомогательные сценарии (ежедневный отчёт в MAX-чат, синхронизация справочников) — на n8n.
Аналитика: от лида до выручки
Главная цель сквозной аналитики — понять, какой источник трафика реально продаёт.
Как это работает:
- В рекламной ссылке UTM-метки в payload (deeplink-параметр для запуска MAX-бота).
- Бот при
/startпарсит payload, сохраняет UTM в сессии пользователя. - При создании сделки в CRM UTM кладутся в кастом-поля сделки (
utm_source,utm_medium,utm_campaign). - Когда сделка переходит в «Оплачено», в BI (Метабаза, DataLens, Tableau) подтягивается выручка.
- Отчёт «выручка по utm_source» показывает реальный ROI каждого канала, а не только цену лида.
Без последнего шага вся работа по UTM теряет смысл — лиды считают все, выручку по источникам — единицы.
Уведомления и SLA
MAX-бот без уведомлений — это просто форма. Нужны четыре типа алертов:
- Менеджеру — мгновенный пинг при новой целевой заявке (в личный MAX через служебного бота, по email, или в Битрикс24-чат).
- Клиенту — подтверждение приёма заявки и срок ответа («с вами свяжутся в течение 30 минут»).
- Руководителю — ежедневный или еженедельный дайджест по воронке (сколько лидов, конверсия, средний чек, источники).
- Алерт об эскалации — если заявка не была взята в работу за N минут, уведомление руководителю или резервному менеджеру.
Это превращает бота из «канала входа» в «инструмент дисциплины» по обработке лидов.
Итого
CRM-бот в MAX — это не «отправлять заявки в API». Полезная связка включает идемпотентную доставку, очередь с ретраями, маппинг полей, двустороннюю синхронизацию через OpenLine или Chat API, идентификацию клиента по max_user_id и сквозную аналитику до выручки. amoCRM подходит для услуг и B2C, Битрикс24 — для крупных B2B-процессов с OpenLine, RetailCRM — для e-commerce, Мегаплан — для проектных продаж. SaaS-конструкторы (n8n, Albato) закрывают простые сценарии, кастом нужен при высокой нагрузке или нестандартной логике. Срок разработки — от 2 недель для базовой связки с одной CRM до 1–2 месяцев для глубокой интеграции с многоступенчатой воронкой и аналитикой. Главная ценность — не в коде, а в продуманной воронке и аккуратной аналитике.
Частые вопросы
Что такое CRM-бот в MAX и чем он отличается от обычного лид-бота?
CRM-бот в MAX живёт с клиентом дольше, чем форма-лидогенератор. Он принимает заявку с уточняющими вопросами, квалифицирует лида (горячий/тёплый/холодный), отсеивает нецелевых, передаёт в amoCRM/Битрикс24/RetailCRM с правильными полями и UTM, шлёт уведомления менеджеру и клиенту, ставит напоминания, поддерживает двустороннюю переписку через OpenLine или Chat API и собирает аналитику воронки до выручки. Обычный лид-бот делает только первый шаг — отправить заявку. CRM-бот закрывает весь цикл от первого касания до сделки.
Сколько стоит интеграция MAX-бота с CRM?
Простая интеграция «заявка из бота → сделка в CRM с UTM-метками» — 50 000–120 000 ₽, срок 1–2 недели. Двусторонняя синхронизация статусов с уведомлениями пользователю — 100 000–250 000 ₽, 2–3 недели. Полноценный диалог из карточки CRM (менеджер пишет в CRM, клиент видит в MAX) через OpenLine-коннектор — от 250 000 ₽, 3–6 недель. Глубокая интеграция с многоступенчатой воронкой, очередью, DLQ, мониторингом и аналитикой — 250 000–600 000 ₽. Простой переход на новую CRM, если бот уже есть и адаптер выделен — 1–2 недели.
Какую CRM выбрать для MAX-бота?
amoCRM — для B2C и услуг: понятный REST API, цифровая воронка с автоматизацией, встроенный мессенджер-канал, виджеты в карточке, лимит 7 RPS. Битрикс24 — для B2B и крупных компаний: мощные права, отделы, бизнес-процессы, OpenLine как канал для бота, лимит 2 RPS на метод. RetailCRM — для интернет-магазинов: интеграции с 1С, эквайрингами, маркетплейсами, бот создаёт заказ напрямую с составом корзины. Мегаплан — для проектных продаж с длинным циклом. Самописная CRM — когда уже есть своя ERP, интеграция через REST/GraphQL/RabbitMQ.
Как сделать двустороннюю синхронизацию между MAX-ботом и CRM?
Два пути. Первый — через готовый канал CRM (amoCRM Chat API, Битрикс OpenLine с кастом-коннектором для MAX): сама CRM держит UI чата, бот выступает коннектором, который шлёт сообщения из CRM в MAX и обратно. Второй — через свой middleware: бот пишет историю в собственную БД, в карточку CRM кладёт ссылку «Открыть переписку», менеджер кликает и попадает в мини-веб-интерфейс с чатом. Первый путь проще и быстрее, второй гибче по UX (шаблоны, быстрые ответы, AI-подсказки, метки настроения клиента, расшифровка голосовых).
Что нужно учесть в интеграции MAX-бота с CRM, чтобы не было сбоев?
Шесть обязательных моментов. Идемпотентность через дедуп-ключ по update_id или хэшу содержимого, чтобы ретраи не задваивали заявки. Очередь Redis/RabbitMQ между ботом и CRM, чтобы при падении CRM лиды не терялись. Учёт rate limits (у amoCRM 7 RPS, у Битрикса 2 RPS на метод). Маппинг полей в ТЗ заранее (источник, UTM, теги, ответственный, max_user_id). Ссылка обратно на чат в карточке. Корректная обработка ошибок: 401/403 не ретраить, 429 уважать Retry-After, 5xx ретраить с exponential backoff и складывать в DLQ после исчерпания попыток.
Как идентифицировать клиента из MAX в CRM?
Самый надёжный способ — попросить телефон через запрос контакта: MAX возвращает номер, привязанный к аккаунту, и этому номеру можно доверять. По нему ищем контакт в CRM или создаём новый. Дополнительно при первом обращении сохраняем max_user_id в кастом-поле контакта — на повторных обращениях находим клиента за один запрос без необходимости снова спрашивать телефон. Для рассылок менеджеры используют deeplink с параметром (payload в стартовой ссылке) — бот при /start понимает, что это конкретный лид из CRM, и сразу его идентифицирует.
Когда брать SaaS-конструктор (n8n, Albato), а когда писать кастом?
Конструктор подходит, если бизнес-логика умещается в DAG из 5–15 шагов, объём до 10 000 сделок в месяц и команда не хочет содержать инфраструктуру. n8n — open-source с self-hosted вариантом, MAX-бот подключается через generic HTTP node. Albato — российский SaaS с фокусом на РФ-сервисы (amoCRM, МойСклад, ЮKassa, Wildberries). Кастом нужен при нестандартных сценариях (AI-анализ диалога перед записью в CRM), высокой нагрузке (сотни тысяч сделок), жёстких требованиях по безопасности (изолированный контур) или двусторонней переписке с богатой UX. Часто оптимален гибрид: критичный путь — кастомом, вспомогательные сценарии — на n8n.