Почему заявки из Telegram теряются, даже если менеджеры «всё видят»
Классическая картина: клиент пишет в Telegram-канал или боту, менеджер отвечает прямо в чате, сделка «как-то» движется — а в CRM по ней ничего нет. Через месяц никто не может сказать, сколько лидов пришло из Telegram, на каком шаге отвалились и кто именно их вёл. Вручную дублировать переписку в CRM никто не успевает: это лишняя рутина, которую физически невозможно делать без ошибок при сколько-нибудь заметном потоке обращений.
Технически задача решается одной связкой: Telegram отправляет вебхук → сервер-приёмник разбирает данные → CRM получает готовую сделку/контакт. Дальше — детали архитектуры, пошаговая реализация на n8n и вариант без no-code слоя, если нужен полный контроль над логикой.
Как устроена связка технически
Вебхук Telegram: что это и как работает
Bot API поддерживает два режима получения обновлений: long polling (бот сам стучится в Telegram и спрашивает «есть что новое?») и webhook (Telegram сам присылает POST-запрос на ваш URL при каждом новом событии). Для интеграции с CRM нужен именно webhook — это единственный вариант с доставкой в реальном времени без постоянного опроса.
Требования Telegram к принимающему серверу:
- адрес обязательно на HTTPS, с валидным сертификатом (TLS 1.2+);
- один из портов: 443, 80, 88 или 8443;
- метод
setWebhookрегистрирует URL, пустая строка в параметреurl— снимает вебхук; - полезно сразу передать
secret_token— Telegram будет присылать его в заголовкеX-Telegram-Bot-Api-Secret-Token, и вы сможете отбрасывать запросы без правильного токена; - у одного бота может быть только один активный вебхук — если используете n8n, платформу автоматизации или свой сервер параллельно, они конкурируют за этот единственный слот.
Регистрация вебхука через curl:
curl -X POST "https://api.telegram.org/bot<TOKEN>/setWebhook" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-domain.ru/webhook/telegram",
"secret_token": "your-random-secret",
"allowed_updates": ["message", "callback_query"]
}'
Что попадает в CRM: лид, сделка, контакт
Прежде чем писать код, нужно решить модель данных на стороне CRM — от этого зависит, что конкретно вебхук должен извлечь из апдейта Telegram:
- Контакт — telegram-username, имя из профиля, chat_id (обязательно сохраняйте — это единственный способ потом написать пользователю в ответ);
- Лид/сделка — текст первого сообщения как описание, источник = «Telegram», привязка к каналу/боту, если их несколько;
- История переписки — не всегда нужна в CRM целиком, но минимум последнее сообщение стоит подтягивать как комментарий к сделке.
Архитектура интеграции: три рабочих варианта
Вариант 1 — n8n как связующий слой (рекомендуется для большинства случаев)
n8n берёт на себя приём вебхука, парсинг, маппинг полей и вызов API CRM — без необходимости поднимать и поддерживать отдельный сервер. Дальше — рабочий сценарий.
Вариант 2 — собственный сервер-приёмник
Node.js/Express, FastAPI или любой другой стек, который сам принимает вебхук и обращается к API CRM. Оправдано, когда логика маппинга сложная (много условий, обогащение данных из сторонних источников, специфичная дедупликация) или когда n8n уже не вписывается в требования по инфраструктуре/безопасности.
Вариант 3 — встроенные интеграции CRM (если есть)
Некоторые CRM (например Bitrix24) имеют «открытые каналы» с готовым коннектором к Telegram без вебхуков вручную. Это быстрее внедрить, но менее гибко: кастомная логика маппинга полей, фильтрация спама, объединение нескольких ботов в одну воронку — обычно требует всё равно выйти за пределы коробочного коннектора.
Пошаговая настройка через n8n
Шаг 1. Создать бота и получить токен
Через @BotFather в Telegram: команда /newbot, задать имя и username, получить токен вида 123456789:AAExxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. Токен — секрет уровня пароля от CRM, хранить только в n8n credentials, не в коде воркфлоу.
Шаг 2. Telegram Trigger в n8n
Нода Telegram Trigger при активации воркфлоу сама регистрирует вебхук в Telegram (вызывает setWebhook) на адрес, который выдаёт n8n. Ручной curl-запрос из раздела выше нужен только если вы делаете кастомный сервер вместо n8n — дублировать регистрацию для одного и того же бота нельзя, останется активным только последний вызов setWebhook.
В настройках триггера выбирайте конкретные типы обновлений (message, при необходимости callback_query для inline-кнопок) — это снижает шум и число лишних срабатываний сценария.
Шаг 3. Разобрать и нормализовать данные
Нода Set (или Code, если маппинг нетривиальный) приводит сырой апдейт Telegram к плоской структуре под CRM:
// Code node — нормализация входящего апдейта Telegram
const msg = $input.first().json.message;
return [{
json: {
chat_id: msg.chat.id,
username: msg.from.username || null,
first_name: msg.from.first_name || '',
last_name: msg.from.last_name || '',
text: msg.text || '',
message_date: new Date(msg.date * 1000).toISOString(),
source: 'telegram'
}
}];
Шаг 4. Проверка на дубль
Без этого шага один активный клиент, который пишет несколько сообщений подряд, породит несколько «лидов» в CRM. Логика на основе chat_id: нода HTTP Request ищет в CRM существующий контакт/сделку по этому идентификатору (обычно поле хранится как «внешний ID» или кастомное поле), и дальше ветвление через IF — создавать новую сущность или дописывать комментарий к существующей.
Шаг 5. Запись в CRM
Дальше — либо готовый нод CRM в n8n (для Bitrix24, HubSpot, Pipedrive и части других систем есть нативные ноды), либо универсальный HTTP Request с вызовом REST API. Общий вид для двух популярных CRM:
Bitrix24 — через входящий вебхук (Настройки → Разработчикам → Другое → Входящий вебхук), без OAuth-приложения:
POST https://ваш-портал.bitrix24.ru/rest/USER_ID/WEBHOOK_KEY/crm.lead.add.json
{
"fields": {
"TITLE": "Обращение из Telegram",
"NAME": "{{ $json.first_name }}",
"SOURCE_ID": "OTHER",
"COMMENTS": "{{ $json.text }}",
"UF_CRM_TELEGRAM_CHAT_ID": "{{ $json.chat_id }}"
}
}
amoCRM — через REST API v4 с OAuth2-токеном интеграции:
POST https://ваш-домен.amocrm.ru/api/v4/leads
Authorization: Bearer {{ access_token }}
[
{
"name": "Обращение из Telegram",
"custom_fields_values": [
{
"field_code": "TELEGRAM_CHAT_ID",
"values": [{ "value": "{{ $json.chat_id }}" }]
}
]
}
]
Названия кастомных полей и точные ID полей всегда свои для каждого аккаунта — их нужно получить через соответствующий метод API (список полей сделки) при настройке, а не угадывать по документации.
Шаг 6. Обратная связь клиенту (опционально, но обычно нужно)
После записи в CRM полезно сразу же сообщить в Telegram, что обращение принято: нода Telegram → sendMessage с chat_id из шага 3. Это снимает часть нагрузки с менеджеров и снижает число повторных сообщений «ну что там».
Вариант без n8n: свой webhook-сервер
Минимальный обработчик на Node.js/Express, если нужен полный контроль или n8n не вписывается в инфраструктуру:
import express from 'express';
const app = express();
app.use(express.json());
const SECRET_TOKEN = process.env.TELEGRAM_SECRET_TOKEN;
app.post('/webhook/telegram', async (req, res) => {
// Проверка, что запрос действительно от Telegram
if (req.header('X-Telegram-Bot-Api-Secret-Token') !== SECRET_TOKEN) {
return res.sendStatus(401);
}
const update = req.body;
const msg = update.message;
if (!msg) return res.sendStatus(200); // не все апдейты — сообщения
await createOrUpdateCrmLead({
chatId: msg.chat.id,
username: msg.from.username,
text: msg.text,
});
// Telegram ждёт быстрый 200 OK, тяжёлую логику лучше выносить в очередь
res.sendStatus(200);
});
app.listen(3000);
Важно: Telegram ждёт ответ в течение нескольких секунд, иначе повторяет отправку апдейта. Долгую логику (запрос к CRM, обогащение данных) стоит выносить в очередь (BullMQ, RabbitMQ и т.п.), а на сам вебхук отвечать 200 сразу после валидации.
Частые ошибки при внедрении
- Забыли secret_token — вебхук принимает вообще любой POST-запрос на нужный URL, а не только от Telegram. Это открытая дверь для спама и подделки лидов.
- Нет дедупликации по chat_id — один диалог превращается в десяток сделок в CRM.
- Два вебхука на одного бота — например, тестовый n8n-воркфлоу и продовый сервер одновременно пытаются вызвать
setWebhook. Активным остаётся только последний, второй молча перестаёт получать апдейты. - Синхронная тяжёлая обработка — если сервер отвечает Telegram дольше нескольких секунд, апдейты начинают дублироваться повторной отправкой.
- Игнорирование лимитов CRM API — при всплеске сообщений (рассылка, вирусный пост) можно упереться в rate limit CRM; нужна очередь с ретраями, а не прямой синхронный вызов из вебхука.
- Хранение токена бота и ключей CRM в коде воркфлоу — только через credentials/секрет-хранилище.
Безопасность: как не превратить вебхук в дыру
- Всегда проверяйте заголовок
X-Telegram-Bot-Api-Secret-Tokenна бэкенде, если делаете свой сервер; - ограничивайте доступ к webhook-эндпоинту по IP, если это возможно (список подсетей Telegram публикуется в документации Bot API и может меняться — фильтрацию по IP стоит держать как дополнительный, а не единственный слой защиты);
- логируйте все входящие вебхуки отдельно от бизнес-логики — это единственный способ быстро разобраться, что произошло, если лид «пропал»;
- для CRM с исходящими вебхуками (события «сделка изменена» и т.п.) в обратную сторону — проверяйте подпись/токен, который CRM присылает, аналогично Telegram.
Чек-лист внедрения
- Бот создан через BotFather, токен сохранён в secrets/credentials;
- Определена модель данных: что в CRM = лид, что = контакт, где хранится chat_id;
- Вебхук зарегистрирован с secret_token и ограниченным списком allowed_updates;
- Реализована дедупликация по chat_id перед созданием сущности в CRM;
- Настроен маппинг кастомных полей CRM (ID полей получены из API, а не угаданы);
- Есть быстрый ответ 200 на вебхук, тяжёлая логика — асинхронно/через очередь;
- Настроена обратная связь клиенту в Telegram после обработки;
- Проверены лимиты API CRM и поведение при их превышении (retry-логика);
- Логирование входящих вебхуков включено отдельно от бизнес-логики.
Частые вопросы (FAQ)
Можно ли подключить несколько Telegram-каналов/ботов к одной CRM?
Да. Каждый бот регистрирует собственный вебхук на свой URL (или на общий URL с параметром, идентифицирующим бота). В n8n это либо отдельные воркфлоу с разными Telegram Trigger, либо один воркфлоу с веткой по bot_id из URL вебхука.
Нужен ли отдельный сервер, если вся автоматизация уже строится в n8n?
Обычно нет — n8n сам поднимает HTTPS-эндпоинт для Telegram Trigger. Отдельный сервер имеет смысл только при нестандартных требованиях к инфраструктуре (изоляция, комплаенс) или очень сложной кастомной логике, которую неудобно вести в визуальном редакторе.
Что делать, если CRM не поддерживает вебхуки/REST API?
Такие системы редки среди современных облачных CRM, но если это так — остаётся RPA-подход (эмуляция действий в интерфейсе) или экспорт/импорт по расписанию через файлы/базу данных. Оба варианта менее надёжны и требуют дополнительного мониторинга.
Как обрабатывать голосовые сообщения, фото и файлы из Telegram, а не только текст?
В апдейте будут поля voice, photo, document вместо text. Файл в Telegram скачивается отдельным вызовом (getFile → получить временную ссылку → скачать), после чего можно приложить его к сделке в CRM через API загрузки файлов конкретной системы.
Безопасно ли пропускать вебхук Telegram напрямую в API CRM без промежуточного слоя?
Технически возможно, но не рекомендуется: пропадает точка для дедупликации, валидации и логирования, а формат данных Telegram и формат полей CRM почти никогда не совпадают один в один. Промежуточный слой (n8n или свой сервер) — это не лишняя сложность, а обязательный слой трансформации и защиты.
