Перенос бота из Telegram в MAX: отличия API и адаптер без переписывания логики
PrimeCoder · 2026 · формат: tech
Разбор новинки простыми словами: что это, кому нужно и брать ли.
Показывает разработчикам и SMB практический путь добавить MAX вторым каналом без переписывания бота — с учётом сертификата Минцифры, вебхука и лимитов.
Связанные услуги: каталог, AI Boost Team, стать клиентом.
Два мессенджера, одно ядро
С февраля 2026 Telegram в России замедляют официально. У части клиентов бот открывается через раз. Жалоб от них не приходит: человек просто молча не дописывает заявку. Автор бота-консультанта на aiogram 3 и FastAPI — история в PostgreSQL, состояния и счётчики в Redis, ответы через Claude — не стал переписывать продукт, а добавил MAX вторым каналом. Вышло несколько сотен строк адаптера.
С февраля 2026 Telegram в России замедляют официально, и часть людей до бота просто не доходит.
Дальше — что в MAX Bot API устроено иначе, чем в Telegram Bot API, и на чём здесь теряют часы.
Что именно сделали
Ядро консультанта — агентный цикл. Берём историю диалога из базы, отдаём модели, крутим инструменты, пока она их просит, получаем текст. Инструмент ровно один: submit_lead. Когда задача клиента понятна, модель заполняет поля заявки, запись ложится в базу, карточка с кнопками уходит в рабочий чат.
Ни одна строка этого цикла не знает, из какого мессенджера пришёл человек. Канал включается одной переменной окружения MAX_BOT_TOKEN. Пустая переменная — клиент MAX равен None, остальное приложение этого не замечает.
Отсюда главный вывод для собственника: цена второго канала зависит не от MAX, а от того, насколько аккуратно у вас отделён транспорт. Если весь бот — это логика, размазанная по хендлерам Telegram, сначала рефакторинг, потом интеграция.
Отличия MAX Bot API, которые бьют первыми
- Хост — platform-api2.max.ru. Старый platform-api.max.ru из ранних примеров уже не тот.
- Токен идёт в заголовке Authorization как есть: без Bearer и без query-параметра.
- Отправка — POST /messages?user_id=… или ?chat_id=…, правка — PUT /messages?message_id=…, ответ на кнопку — POST /answers?callback_id=….
- Лимиты: 30 запросов в секунду, 4000 знаков в тексте сообщения. На 429 клиент делает паузу в секунду и повторяет один раз, длинный ответ модели режется по абзацам и пробелам.
- Клавиатура — вложение типа inline_keyboard, кнопки двух видов: callback с payload и link с url.
- Подписка на типы обновлений: message_created, message_callback, bot_started, bot_added, bot_admin_permissions_changed. Два последних — бытовая вещь: когда бота добавляют в группу и делают админом, он сам присылает идентификатор чата.
- В группах бот видит события только с правом администратора «читать все сообщения». Без него он слепой и молчит.
- Метка диплинка — до 128 символов.
Сертификат Минцифры и вебхук, который глушит polling
Больше всего времени съел сертификат. platform-api2.max.ru отдаёт цепочку «Russian Trusted Sub CA» — это Минцифры. В стандартных наборах корневых сертификатов её нет, aiohttp честно падает с CERTIFICATE_VERIFY_FAILED. Отключать проверку нельзя: токен бота уйдёт первому, кто встанет посередине. Решение — подсунуть промежуточный сертификат доверенным якорем только клиенту MAX и включить флаг VERIFY_X509_PARTIAL_CHAIN. Системное хранилище и соединения с Telegram и Anthropic остаются нетронутыми. Отпечаток сертификата записан в README: при плановой замене будет с чем сравнить.
Второй сюрприз — доставка обновлений. В разработке удобен long polling: GET /updates с маркером, почти как getUpdates. В бою MAX требует вебхук: подписка через POST /subscriptions, адрес на HTTPS и порту 443, ответ 200 нужно вернуть за 30 секунд. Caddy с Let’s Encrypt закрывает это без усилий.
Пока подписка активна, long polling с тем же токеном молча ничего не получает.
На этом месте автор потерял час: локальный бот запускается, ошибок нет, сообщения не приходят. Теперь приложение в режиме polling при старте смотрит список подписок и пишет предупреждение в лог. Обработчик вебхука короткий: неизвестный секрет в пути — 404, неверный заголовок X-Max-Bot-Api-Secret — 403, само обновление уходит в фоновую задачу, чтобы уложиться в 30 секунд.
Одна таблица на два мессенджера
Пользователи Telegram и MAX лежат в одной таблице users. Чтобы пространства идентификаторов не пересеклись, id из MAX хранится отрицательным, а поле channel говорит, откуда человек. Тот же приём в Redis: антифлуд и дневной бюджет токенов считаются по тому же отрицательному id, отдельных веток в коде нет. Защита от повторной доставки — ключ в Redis по update_type, ident и timestamp.
Кому нужно и где подвох
Этот путь имеет смысл, если у вас уже есть отделённое ядро и живая аудитория, которая перестала доходить. И если вы готовы держать свой домен с валидным HTTPS — без него вебхук не заведётся, локально в песочнице не погоняешь.
Подвох в обслуживании. Сертификат придётся обновлять и сверять по отпечатку. Текст резать по 4000 знаков. Обрабатывать 429 и не рассчитывать, что «30 запросов в секунду всегда хватит». И помнить, что тестировать можно без боевого токена, но проверять доставку — только на реальном HTTPS-адресе.
Брать или подождать: вердикт за 30 секунд
Брать, если логика бота уже отделена от Telegram и вы теряете клиентов на входе. Неделя работы против потерянных заявок, которые вы даже не считаете. Подождать, если бот — это набор хендлеров с логикой внутри: сначала технический долг, иначе второй канал удвоит его. И не брать ради галочки «мы в MAX» — канал без замеров конверсии покупает файл, а не решение.
Факт → что это значит
- Сертификат Russian Trusted Sub CA в цепочке → стандартная проверка SSL ломается, нужен свой якорь доверия; отключение проверки — прямая утечка токена.
- Вебхук обязателен в бою, 200 за 30 секунд → синхронная тяжёлая логика в обработчике не пройдёт, только фоновая задача.
- Активная подписка глушит polling без ошибок → «бот не отвечает» чаще всего означает конфликт режимов, а не баг в коде.
- Отрицательный id MAX в общей таблице → миграции и ключи Redis остаются прежними, второй набор таблиц не нужен.
- 4000 знаков и 30 запросов в секунду → длинные ответы модели надо резать заранее, а не ловить 429 в проде.
Вопросы, которые задают первыми
Нужно ли переписывать бота целиком?
Нет, если логика отделена от мессенджера. Адаптер повторяет контракт пользователя и транспорта, ядро остаётся как было.
Можно ли проверить всё без боевого токена?
Да, сборку и обработчики — можно. Доставку вебхука — только на живом HTTPS-адресе с портом 443.
Что сломается первым после запуска?
Сертификат и конфликт подписки с polling. Оба лечатся заранее: якорь доверия в конфиге и проверка списка подписок на старте.
Что делать на этой неделе
Посчитайте, сколько диалогов вы не теряете в Telegram. Если цифра неизвестна — вы не готовы считать второй канал окупаемым, начинайте с аналитики входа. Если известна — вынесите транспорт из хендлеров, заведите общий идентификатор пользователя с полем channel и поднимите тестовый домен с валидным сертификатом. Дальше MAX подключается переменной окружения, а не вторым проектом.
PrimeCoder Team · Официальный ответ · PrimeCoder
Напишите объём лидов, средний чек и базовую конверсию — прикинем экономику пилота и горизонт окупаемости под ваш цифры.