Как подключить Telegram-бота к CRM и формам: базовая схема передачи лидов без сайта

На чтение
8 мин
Дата обновления
05.11.2026

Реклама может вести сразу в Telegram-бота: человек выбирает услугу, оставляет контакт и подтверждает отправку заявки. Менеджер при этом получает карточку в CRM, а не ищет нужный диалог среди сообщений. Отдельная посадочная страница для такого маршрута не обязательна. Однако «без сайта» не означает «без серверной части»: кто-то должен принимать события бота, хранить состояние разговора и обращаться к CRM.

Разберём авторскую схему для небольшой команды, которая продаёт консультации. В качестве CRM возьмём Битрикс24 и создадим лид через универсальный crm.item.add с entityTypeId=1. Лид здесь — входящее обращение; создание лида само по себе не создаёт сделку и не подтверждает продажу. Переход к сделке команда настраивает отдельно.

Что связывает бот и CRM

Прямого перехода «любое сообщение — новая карточка» лучше избегать: приветствие, исправление имени и повторное нажатие кнопки превратятся в разные лиды. Между Telegram и CRM предусмотрим небольшой интеграционный сервис с хранилищем и очередью. Он собирает одну законченную заявку и только после подтверждения передаёт её дальше.

УчастокОтветственность в нашей схеме
БотВопросы, кнопки, показ собранных данных и сообщение о результате
HTTPS-приёмникПроверка входящего события и надёжная запись в очередь
ОбработчикСостояние диалога, проверка полей, предотвращение повторной обработки
CRMКарточка лида, ответственный менеджер и дальнейшая работа
Журнал интеграцииСвязь заявки с событиями и идентификатором созданного лида

Если нужен только ответ оператора в чате, подобная связка может оказаться избыточной. Она полезна, когда важно распределять обращения, видеть незавершённые запросы и сверять количество подтверждённых заявок с CRM. Выбор здесь зависит от рабочего процесса, а не от наличия красивой кнопки.

Маршрут человека: от ссылки до подтверждения

Для учебной кампании используем ссылку https://t.me/your_bot?start=consult_demo. В личном чате deep link передаёт параметр start; документация Telegram допускает буквы A–Z и a–z, цифры, подчёркивание и дефис, длину до 64 символов. Это удобная метка кампании, но не надёжное удостоверение личности. Не помещайте в неё пароль, телефон или секрет интеграции.

Наш бот предлагает выбрать «Первая консультация» или «Повторное обращение», затем спрашивает имя и удобный контакт. Кнопка клавиатуры с request_contact позволяет отправить номер пользователя и доступна в личном чате. Альтернатива — вручную введённый контакт. Не считайте произвольный текст телефона доказательством владения номером.

Далее бот показывает итог: «Услуга: первая консультация. Имя: Анна. Контакт: указанный вами номер. Заявка будет передана менеджеру компании N». Кнопки «Изменить» и «Отправить заявку» завершают понятный человеку сценарий. В нашей реализации обработчик сохраняет факт подтверждения и версию показанного текста. Это проектирование интерфейса, а не утверждение, что такое нажатие автоматически выполняет все юридические требования к обработке данных.

Для inline-кнопки можно передать короткий callback_data, например submit:lead17. Bot API ограничивает это поле 1–64 байтами. Полную заявку храните на сервере, а по короткому ключу находите её состояние. На callback отвечайте методом answerCallbackQuery; отдельно проверяйте, что именно этот пользователь подтверждает свою ещё не отправленную заявку. Кнопка сама по себе не заменяет проверку состояния.

Два разных webhook

В Telegram метод setWebhook задаёт HTTPS-адрес, на который платформа отправляет POST с JSON-объектом Update. При неуспешном ответе, то есть статусе вне 2XY, доставка повторяется ограниченное число раз. Параметр secret_token позволяет получить специальный заголовок X-Telegram-Bot-Api-Secret-Token. Наш приёмник должен проверять его перед разбором заявки, а секрет хранить в серверной конфигурации.

Webhook Telegram — входящее событие. Авторизационный адрес REST-интеграции CRM — другой секрет и другой участок маршрута. Не вставляйте CRM-адрес с ключом в сообщение бота, клиентскую форму, скриншот или публичный репозиторий. Сервис обращается к CRM от своего имени с предусмотренными для интеграции правами.

После проверки и надёжной записи события приёмник может вернуть успешный HTTP-ответ, а дальнейшую работу выполнить из очереди. Если ответить успехом до сохранения, сбой процесса способен потерять заявку; если ждать CRM внутри каждого webhook, её задержки будут мешать приёму новых событий. Это выбранная нами архитектура, а не требование использовать конкретную очередь или облачный продукт.

Поля: переводим разговор в карточку

Перед интеграцией запросите crm.item.fields с entityTypeId=1 на своём портале: метод описывает поля и их конфигурацию. Не переносите вслепую набор из чужого примера: у вашей команды могут быть собственные поля и условия. В минимальном учебном запросе отделим имя от названия обращения, а источник сохраним в комментарии.

{
  "entityTypeId": 1,
  "fields": {
    "title": "Консультация: заявка из Telegram",
    "name": "Анна",
    "comments": "Учебный пример; услуга: первая консультация; кампания: consult_demo; внутренний ключ: lead17"
  }
}

Такое тело предназначено для crm.item.add после настройки авторизации и проверки полей конкретного портала. Для телефона универсальный API использует мультиполе fm: массив с typeId, valueType и value. Например, {"typeId":"PHONE","valueType":"WORK","value":"555888"} внутри массива fm. Число здесь демонстрационное: его не отправляют как настоящий контакт.

В старых инструкциях встречаются crm.lead.add, crm.lead.fields и поля TITLE/PHONE. Оба специализированных метода в документации помечены DEPRECATED: их развитие остановлено, рекомендованы crm.item.add и crm.item.fields. Не смешивайте прежний формат PHONE с новым fm. Пример выше использует универсальный API и строчные имена стандартных полей.

Сохраните идентификатор result.item.id из успешного результата crm.item.add рядом с внутренним ключом заявки. Сообщение «Заявка передана» отправляйте после подтверждённого результата, а при записи только в очередь говорите точнее: «Заявка принята в обработку». Пользовательские данные не должны превращаться в бесконтрольную копию всего диалога внутри COMMENTS.

Почему одной проверки телефона недостаточно

Дубликат события и повторное обращение человека — разные вещи. Update содержит update_id, уникальный идентификатор обновления. В нашем журнале сочетание идентификатора бота и update_id имеет уникальное ограничение: повтор доставки того же события не запускает обработку заново.

У законченной заявки есть отдельный внутренний ключ lead17. Повторное нажатие «Отправить» проверяет её состояние: уже созданному лиду соответствует сохранённый CRM ID. Но новая консультация того же человека не обязана исчезать только потому, что телефон уже встречался. Правило объединения контактов и обращений согласуйте с работой менеджеров.

Особенно важен неоднозначный сбой: CRM могла создать лид, но ответ потерялся по дороге. Слепой повтор crm.item.add способен создать вторую карточку. В нашей схеме такое задание получает состояние «результат неизвестен» и идёт на сверку. Можно разработать поиск по отдельному внешнему ключу в настроенном поле, но наличие этого поля и способ поиска нужно реализовать и проверить отдельно. Мы не предполагаем, что CRM автоматически обеспечивает идемпотентность любого запроса.

Если заявку присылает форма

Ту же очередь можно использовать для формы в другом сервисе. Добавьте адаптер, который проверяет предусмотренную поставщиком авторизацию webhook и переводит его поля во внутренний формат: ключ события, источник, имя, контакт, услуга и подтверждение пользователя. Схема Telegram Update к сторонней форме не применяется.

Например, условный поставщик прислал событие {"event_id":"form-28","full_name":"Анна","service":"consult","contact":"указанный контакт"}. Это наш учебный формат, а не стандарт всех форм. Адаптер создаёт внутренний ключ события form:provider_a:form-28, записывает name из full_name, выбранную услугу из service и источник form/provider_a. После проверки контакта и подтверждения обработчик собирает те же поля title, name, comments и при необходимости fm. Для другого поставщика названия полей и способ проверки подлинности будут другими.

Что ломается до появления карточки

СимптомЧто проверяем
Telegram не доставляет событияHTTPS-адрес приёмника, ответы сервера и getWebhookInfo; неверный secret token не принимаем как доверенное событие
Кнопка нажата, но заявка не движетсяОбработку callback, answerCallbackQuery и состояние подтверждения в журнале
CRM вернула INVALID_CREDENTIALSАктивность и корректность webhook-учётных данных; не создаём новую заявку вместо исправления доступа
ACCESS_DENIED или insufficient_scopeПрава пользователя интеграции и доступный scope crm
expired_tokenСрок действия OAuth access-токена и штатный механизм его обновления; не путать с секретом входящего webhook
QUERY_LIMIT_EXCEEDEDОграничение интенсивности запросов; управляем очередь и повтор по правилам API, не отправляем бесконечный цикл
Ошибка значения или обязательного поляМетаданные своего портала, типы и поля, обязательные для выбранной стадии

Договоритесь, что делать с пустым контактом, неизвестной услугой и повторным событием формы. Лучше явно отклонить некорректное задание и показать причину оператору, чем создать внешне успешную карточку без данных для связи. В журнале оставляйте технические идентификаторы и необходимую диагностику; доступ и сроки хранения персональных сведений определяйте отдельно.

Приёмка: сверяем не только красивое сообщение

На тестовом боте и тестовой CRM пройдите маршрут целиком: ссылка кампании → вопросы → исправление контакта → подтверждение → один лид с правильными полями. Затем повторно доставьте то же событие, дважды нажмите отправку, смоделируйте отказ CRM и неизвестный результат после таймаута. Проверьте не только экран пользователя, но и очередь, журнал и количество карточек.

Эти испытания здесь предложены как план приёмки, а не как отчёт о подключении реального портала. Готовая интеграция должна позволять ответить на конкретный вопрос: «Куда делась заявка lead17?» Если видны время приёма, состояние обработки, причина сбоя и CRM ID, проблему можно исправить без повторного расспроса клиента.