Найти в Дзене
Глубже некуда

Макс для автоматизаторов: Bot API, интеграции и сравнение с Telegram и WhatsApp

Макс - это мессенджер, где разработчику официально предлагают не «пишите бота, как хотите», а «сначала станьте правильной организацией, потом поговорим». Подключение к платформе для партнёров и доступ к чат-ботам/мини-приложениям/каналам прямо в документации помечены как доступные лишь ограниченному списку юрлиц и ИП (через RuStore или МСП.РФ), а самозанятым и физлицам вход пока закрыт. Технически Bot API Макс - это HTTP(S) REST-подобный интерфейс на домене https://platform-api.max.ru, а не WebSocket и не gRPC. События приходят либо через Webhook (push), либо через Long Polling (GET /updates) - одновременно нельзя, а для production документация прямо рекомендует Webhook. По «железным фактам» из официальной документации: С каналами есть важная «бизнесовая реальность»: документация про создание каналов говорит, что публикация постов и управление контентом происходит в интерфейсе мессенджера, а не через публичный API. То есть «постинг в канал через API» официально не описан, и это надо п
Оглавление
Макс для автоматизаторов: Bot API, интеграции и сравнение с Telegram и WhatsApp
Макс для автоматизаторов: Bot API, интеграции и сравнение с Telegram и WhatsApp

Макс - это мессенджер, где разработчику официально предлагают не «пишите бота, как хотите», а «сначала станьте правильной организацией, потом поговорим». Подключение к платформе для партнёров и доступ к чат-ботам/мини-приложениям/каналам прямо в документации помечены как доступные лишь ограниченному списку юрлиц и ИП (через RuStore или МСП.РФ), а самозанятым и физлицам вход пока закрыт.

Технически Bot API Макс - это HTTP(S) REST-подобный интерфейс на домене https://platform-api.max.ru, а не WebSocket и не gRPC. События приходят либо через Webhook (push), либо через Long Polling (GET /updates) - одновременно нельзя, а для production документация прямо рекомендует Webhook.

По «железным фактам» из официальной документации:

  • аутентификация - простым токеном бота в заголовке Authorization: <token>, передача токена в query больше не поддерживается; токен можно обновлять (ротировать).
  • базовый лимит нагрузки - ориентир 30 rps на platform-api.max.ru, а при превышении - ожидайте 429.
  • сообщения - JSON, text до 4000 символов, форматирование Markdown или HTML, есть упоминания через max://user/user_id, есть inline-клавиатуры и callback-ответы через отдельный метод.
  • медиа грузится «в два шага»: POST /uploads даёт URL, потом заливаете файл, потом прикрепляете token в attachments; есть нюанс с обработкой (ошибка attachment.not.ready) и отдельная механика для видео/аудио.
  • редактирование/удаление сообщений - только для сообщений моложе 24 часов, и удаление зависит от разрешений.
  • чтобы ловить события из групповых чатов или каналов, бота нужно сделать администратором.

С каналами есть важная «бизнесовая реальность»: документация про создание каналов говорит, что публикация постов и управление контентом происходит в интерфейсе мессенджера, а не через публичный API. То есть «постинг в канал через API» официально не описан, и это надо проговаривать заранее, чтобы не было сюрприза в стиле «мы уже подписали SLA».

Сравнение по интеграции:

  • Telegram - максимально инженерный в плане входа: Bot API - чистый HTTPS, вебхук или long polling, понятные лимиты (например, массовые рассылки около 30 msg/sec и типичные 429 при превышении), плюс богатая экосистема.
  • WhatsApp для бизнеса - это Graph API и webhooks, токены доступа, жёсткие продуктовые ограничения (шаблоны вне «окна», лимиты на отправку и качество), зато очень зрелая модель статусов доставки/прочтения и ожидания enterprise-уровня.
  • Макс - «молодая» платформа, но уже с внятным REST, вебхуками, правами администраторов и большой ставкой на мини-приложения (MAX Bridge + валидация initData через HMAC).

Где Макс живет в экосистеме автоматизации

Если ты автоматизатор и хочешь «просто токен и поехали», Макс сначала попросит тебя доказать, что ты бизнес. В документации прямо сказано:

  • подключение к партнёрской платформе и сервисам (чат-боты, мини-приложения, каналы) пока доступно ограниченному списку юрлиц и ИП (например, кто разместил приложение в RuStore или зарегистрировался на МСП.РФ).
  • самозанятые, физические лица и нерезиденты пока не могут авторизоваться или зарегистрироваться на платформе.

С практической точки зрения это влияет на архитектуру интеграций сильнее, чем выбор языка:

  • жизненный цикл бота включает модерацию, а токен появляется после успешной проверки (и его можно обновлять).
  • на одну организацию - до 5 ботов.
  • создание бота делается через платформу business.max.ru (UI), а не через публичный API.

Историческая ремарка: Макс связывают с VK как разработчиком/инициатором, но для интегратора важнее не происхождение, а то, что официальный dev-портал и публичный Bot API уже существуют и описаны.

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

Bot API Макс: протоколы, объекты, авторизация, ограничения

Типы API и транспорт

  • Официально описан HTTPS API на platform-api.max.ru с методами GET/POST/PUT/PATCH/DELETE и ответами JSON.
  • Push-события - Webhook через POST /subscriptions, Pull-события - Long Polling через GET /updates.
  • WebSocket/gRPC в официальной документации Bot API не заявлены (если где-то в интернете видишь «WebSocket API Макс», это почти наверняка про неофициальные клиентские/реверсные штуки). Например, сторонняя Python-библиотека описывает работу через WebSocket и вход по номеру телефона - это другой класс интеграций (и другой уровень риска).

Аутентификация

  • Токен бота выдаётся на платформе для партнёров после модерации, и это «прямой доступ к боту», его рекомендуют не светить и при подозрении на компрометацию - обновлять.
  • В запросах токен передаётся заголовком Authorization: <token>. Передача через query-параметры больше не поддерживается.
  • Формально в API-описании это обозначено как apiKey (то есть это не OAuth 2.0, не JWT со сроком жизни, не refresh-токены - просто ключ).

Авторизация и права

  • Для групповых чатов есть права (permissions) уровня администратора: read_all_messages, add_remove_members, add_admins, change_chat_info, pin_message, write, а также дополнительные вроде edit_message, delete_message и др. - они возвращаются, например, в GET /chats/{chatId}/members/me.
  • Чтобы получать события из группового чата или канала, бота нужно назначить администратором.
  • Удаление сообщений через DELETE /messages возможно только если у бота есть разрешение на удаление, и тоже ограничено по времени (см. ниже).

Форматы сообщений

  • POST /messages принимает text (до 4000 символов) и attachments, плюс флаги вроде notify и format (markdown или html).
  • Форматирование: либо Markdown, либо HTML; упоминание пользователя делается ссылкой на max://user/user_id.
  • Inline-клавиатура: до 210 кнопок, 30 рядов, до 7 кнопок в ряду (а для отдельных типов - меньше), ссылки до 2048 символов; типы кнопок включают callback, link, request_contact, request_geo_location, open_app, message.
  • Нажатия callback-кнопок обрабатываются через update типа message_callback, а ответ отправляется методом POST /answers?callback_id=... и может обновить сообщение и/или показать одноразовое уведомление.

Ограничения и квоты

  • Практический лимит: для стабильной работы ботов рекомендуют считать максимум 30 rps на platform-api.max.ru; при превышении ожидаем 429.
  • Редактирование сообщений PUT /messages - только если сообщение отправлено менее 24 часов назад.
  • Удаление сообщений DELETE /messages - тоже только для сообщений младше 24 часов, плюс нужны права.
  • Webhook: должен быть HTTPS, HTTP не поддерживается; можно самоподписанный сертификат. При подписке сервер должен слушать один из разрешённых портов (80/8080/443/8443/16384-32383).

Доставка, подтверждения, «а точно дошло?»

  • Для Long Polling есть важная семантика: ответы GET /updates содержат marker, который указывает на следующий ожидаемый апдейт; «все предыдущие считаются завершёнными после прохождения marker». Это почти готовая модель «подтверждения» обработки на стороне клиента, если правильно хранить marker.
  • Для «прочитано» у ботов есть действие mark_seen через POST /chats/{chatId}/actions. Это полезно как управляемый read-receipt со стороны бота.
  • В объекте Message есть поле stat типа MessageStat, но публично структура MessageStat в видимом списке объектов описана не полностью - так что надёжный способ строить аналитику доставки по этому полю пока не получится без экспериментов.

Медиа: хранение, загрузка и боль обработки

  • POST /uploads?type=image|video|audio|file возвращает URL для загрузки; загрузка может быть multipart (просто) или resumable (надёжнее, с возобновлением). При multipart есть лимит 4 ГБ и «один файл за раз».
  • Токен для прикрепления потом используется в attachments. Есть нюансы по типам (для видео/аудио в документации отдельно описана механика) и есть типовая ошибка attachment.not.ready если отправить сообщение слишком быстро после загрузки - предлагается пауза и повтор с увеличением интервала, либо заранее загружать и переиспользовать токены.

Мини-приложения и фронтенд-интеграции (CORS/CSP тут реально важны)

  • Для мини-приложений есть MAX Bridge: <script src="https://st.max.ru/js/max-web-app.js"></script> даёт доступ к window.WebApp, стартовым данным и событиям клиента.
  • Стартовые параметры (initData) нужно валидировать: описана процедура HMAC-SHA256 с ключом "WebAppData" и Bot Token, сортировка ключей, исключение hash, разделитель \n. Это похоже на подход Telegram Web Apps, и да - это тот случай, когда «не проверять подпись» значит «самому себе выдать админку».
  • Практика безопасности для мини-приложения: жёсткий CSP (запрет inline-скриптов где возможно, allowlist доменов, запрет connect-src *), аккуратный CORS (разрешать только нужные origin), и серверная валидация initData перед любыми чувствительными действиями. (Это уже best practice, не «факт документации».)

Реалистичная архитектура интеграции и два режима получения событий

Ниже - «нормальная» архитектура, которую можно поставить в production и не ненавидеть себя через месяц.

-2

Ключевые детали, которые стоит заложить сразу:

  • Webhook как режим production: в документации прямо сказано - для production используйте только Webhook, а Long Polling - для разработки и тестов.
  • Секрет в заголовке: при подписке можно указать secret, и тогда в каждом webhook-запросе будет заголовок X-Max-Bot-Api-Secret. Проверка этого заголовка - минимальный baseline (иначе твой endpoint превращается в публичный «вход в систему по URL»).
  • Idempotency: Макс не описывает официальный Idempotency-Key как в Stripe, поэтому делаем прикладной dedup:для webhook: ключ дедупликации по (update_type, message.body.mid) или (update_type, callback_id); хранить в Redis с TTL.
    для long polling: базовый ключ - marker, хранить last seen marker durably.
  • Retry/backoff: платформой задокументированы 429 и 503, а для медиа известна ошибка attachment.not.ready - всё это требует экспоненциального backoff с jitter и ограничением по времени.
  • Rate limit: ориентация на 30 rps - значит, если у тебя воркеров 20, им нельзя «всем дружно» долбить API. Нужен общий клиентский rate limiter (token bucket) на процесс/кластер.

Теперь sequence-диаграмма «пришло сообщение - ответили - подтвердили кнопку».

-3

Практика: curl и SDK-стиль на Python и Node.js

Ниже примеры специально сделаны так, чтобы их было не стыдно положить в репозиторий: реальные URL, заголовки, JSON, обработка ошибок, backoff, и аккуратное отношение к «повторным доставкам».

Регистрация бота и получение токена

Факт: публичного API для «создать бота» в документации нет - бот создаётся на платформе для партнёров и проходит модерацию; токен появляется после этого.

Что можно автоматизировать с нуля:

  • проверку, что токен рабочий: GET https://platform-api.max.ru/me.

curl -sS -X GET "https://platform-api.max.ru/me" \
-H "Authorization: ${MAX_BOT_TOKEN}"

Отправка сообщений: личка и групповой чат

cURL: сообщение пользователю

curl -sS -X POST "https://platform-api.max.ru/messages?user_id=1234567890" \
-H "Authorization: ${MAX_BOT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"text": "Привет! Это тест интеграции.",
"format": "markdown",
"notify": true
}'

cURL: сообщение в групповой чат

curl -sS -X POST "https://platform-api.max.ru/messages?chat_id=987654321" \
-H "Authorization: ${MAX_BOT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"text": "**Системное сообщение**\nПошла обработка задачи.",
"format": "markdown",
"notify": false
}'

Публикация в канал через API

Вот здесь начинается честная часть (она же самая полезная).

  • В документации по каналам сказано, что публикация постов делается в интерфейсе мессенджера, то есть публичного «post-to-channel API» не описано.
  • При этом в Message есть поле url - «публичная ссылка на пост в канале» (и оно отсутствует для диалогов и групповых чатов). Это намекает, что каналы внутри системы существуют как получатели сообщений, но как именно их адресовать публично - не раскрыто.
  • Плюс отдельная ремарка: чтобы получать события из канала, бота нужно сделать админом.

Вывод: официально подтверждённый сценарий «пост в канал по API» - неуточнено. Безопасная позиция в проекте: либо вы публикуете в канал руками/через мини-приложение, либо договариваетесь, что API-постинг делается только если платформа/поддержка Макс подтвердит способ получить chat_id канала и разрешит писать боту.

Если у вас уже есть внутренний chat_id канала (неважно как вы его получили, это за рамками публичной доки), то «наиболее вероятная» структура отправки выглядит так же, как в чат:

# НЕУТОЧНЕНО официально: сработает только если канал адресуется chat_id и бот имеет право write в канале
curl -sS -X POST "https://platform-api.max.ru/messages?chat_id=${CHANNEL_CHAT_ID}" \
-H "Authorization: ${MAX_BOT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"text": "Пост в канал (если платформа это разрешила).",
"notify": true
}'

Основание для такой гипотезы - единый POST /messages?chat_id=... и наличие url для постов в канале в объекте Message, но повторюсь: официально это не описано как публичный контракт.

Webhook: подписка, проверка секрета, обработка update

Подписка на Webhook (cURL)
Обрати внимание на:

  • url строго https://...
  • secret ограничен regex и уходит в заголовок X-Max-Bot-Api-Secret
  • порты у сервера должны быть из allowlist (иначе подпишешься, но не взлетит)

curl -sS -X POST "https://platform-api.max.ru/subscriptions" \
-H "Authorization: ${MAX_BOT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-domain.com/webhook/max",
"update_types": ["message_created", "message_callback", "bot_started"],
"secret": "my_secret_12345"
}'

Python (FastAPI): webhook handler + ответ на сообщение

import os
import time
import random
import requests
from fastapi import FastAPI, Request, HTTPException

MAX_API_BASE = "https://platform-api.max.ru"
BOT_TOKEN = os.environ["MAX_BOT_TOKEN"]
WEBHOOK_SECRET = os.environ["MAX_WEBHOOK_SECRET"]

session = requests.Session()
session.headers.update({"Authorization": BOT_TOKEN})

app = FastAPI()

def _sleep_backoff(attempt: int, base: float = 0.4, cap: float = 10.0) -> None:
# exponential backoff + jitter
delay = min(cap, base * (2 ** attempt))
delay = delay * (0.5 + random.random())
# jitter
time.sleep(delay)

def max_api_post(path: str, *, params: dict | None = None, json: dict | None = None) -> dict:
url = f"{MAX_API_BASE}{path}"
last_err = None
for attempt in range(6):
try:
r = session.post(url, params=params, json=json, timeout=10)
if r.status_code in (429, 503):
_sleep_backoff(attempt)
continue
r.raise_for_status()
return r.json()
except Exception as e:
last_err = e
_sleep_backoff(attempt)
raise RuntimeError(f"MAX API POST failed after retries: {last_err}")

def send_message_to_chat(chat_id: int, text: str, *, fmt: str | None = None) -> dict:
body = {"text": text}
if fmt:
body["format"] = fmt
# "markdown" or "html"
return max_api_post("/messages", params={"chat_id": chat_id}, json=body)

def answer_callback(callback_id: str, notification: str) -> dict:
return max_api_post("/answers", params={"callback_id": callback_id}, json={"notification": notification})

@app.post("/webhook/max")
async def max_webhook(req: Request):
# 1) verify secret header
secret = req.headers.get("X-Max-Bot-Api-Secret")
if secret != WEBHOOK_SECRET:
raise HTTPException(status_code=403, detail="bad secret")

# 2) parse update
update = await req.json()
utype = update.get("update_type")

# 3) fast ack principle - do minimal work here
if utype == "message_created":
msg = update.get("message", {})
recipient = msg.get("recipient", {})
chat_id = recipient.get("chat_id")
if isinstance(chat_id, int):
# respond
send_message_to_chat(chat_id, "Принял. Обрабатываю.", fmt="markdown")

elif utype == "message_callback":
cb = update.get("callback", {})
callback_id = cb.get("callback_id")
if callback_id:
answer_callback(callback_id, "Ок, нажато.")

return {"ok": True}

Факты, на которые опирается пример: POST /subscriptions с secret формирует заголовок X-Max-Bot-Api-Secret, есть update типы и есть POST /answers, а сообщения отправляются через POST /messages на platform-api.max.ru.

Long polling: когда нужно и как не потерять события

Официальная модель GET /updates:

  • timeout до 90 секунд
  • limit до 1000
  • marker - курсор, который «подтверждает» получение предыдущих апдейтов

curl -sS -X GET "https://platform-api.max.ru/updates?timeout=30&limit=50&types=message_created,message_callback" \
-H "Authorization: ${MAX_BOT_TOKEN}"

Node.js: long polling loop (SDK-style клиент)

import fetch from "node-fetch";

const BASE = "https://platform-api.max.ru";
const TOKEN = process.env.MAX_BOT_TOKEN;

async function sleep(ms) {
await new Promise((r) => setTimeout(r, ms));
}

async function getUpdates({ marker, timeout = 30, limit = 100, types } = {}) {
const url = new URL(`${BASE}/updates`);
url.searchParams.set("timeout", String(timeout));
url.searchParams.set("limit", String(limit));
if (marker !== undefined && marker !== null) url.searchParams.set("marker", String(marker));
if (types?.length) url.searchParams.set("types", types.join(","));

const res = await fetch(url.toString(), {
method: "GET",
headers: { Authorization: TOKEN },
});

if (res.status === 429 || res.status === 503) {
const txt = await res.text();
throw new Error(`retryable ${res.status}: ${txt}`);
}
if (!res.ok) {
const txt = await res.text();
throw new Error(`http ${res.status}: ${txt}`);
}
return await res.json();
}

async function sendMessageToChat(chatId, text) {
const url = new URL(`${BASE}/messages`);
url.searchParams.set("chat_id", String(chatId));

const res = await fetch(url.toString(), {
method: "POST",
headers: {
Authorization: TOKEN,
"Content-Type": "application/json",
},
body: JSON.stringify({ text, notify: true }),
});

if (!res.ok) {
const txt = await res.text();
throw new Error(`sendMessage failed ${res.status}: ${txt}`);
}
return await res.json();
}

async function main() {
let marker = null;

for (;;) {
try {
const page = await getUpdates({
marker,
timeout: 30,
limit: 100,
types: ["message_created"],
});

const updates = page.updates || [];
for (const u of updates) {
if (u.update_type === "message_created") {
const chatId = u.message?.recipient?.chat_id;
if (typeof chatId === "number") {
await sendMessageToChat(chatId, "pong");
}
}
}

// commit marker AFTER processing
marker = page.marker ?? marker;
} catch (e) {
// backoff for retryable errors
await sleep(800);
}
}
}

main().catch((e) => {
console.error(e);
process.exit(1);
});

Основание: описание GET /updates с marker/timeout/limit/types и общая модель авторизации/JSON.

Кнопки, inline-кнопки и «псевдо-карусель»

Inline-кнопки (cURL)

bashCopycurl -sS -X POST "https://platform-api.max.ru/messages?chat_id=987654321" \
-H "Authorization: ${MAX_BOT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"text": "Выберите действие",
"attachments": [{
"type": "inline_keyboard",
"payload": {
"buttons": [[
{ "type": "callback", "text": "Обновить", "payload": "refresh" },
{ "type": "link", "text": "Открыть сайт", "url": "https://example.com" }
]]
}
}]
}'

Обработка callback

  • ловите update message_callback
  • достаёте callback_id
  • отвечаете POST /answers?callback_id=... (можно обновить сообщение или показать notification)

Про «карусели» честно:

  • В публичной документации Bot API Макс я не нашёл отдельного attachment-типа «carousel». В официальной JS-библиотеке показывают вложения (image/video/audio/file/sticker/location/share) и клавиатуры, но не «карусель» как у некоторых платформ. Значит, это либо отсутствует, либо реализуется через мини-приложение/редактирование сообщений.

Практический обходной путь, который обычно работает в мессенджерах:

  • отправляете одно сообщение с «карточкой #1» и inline-кнопками «вперёд/назад»
  • по callback делаете PUT /messages и подменяете текст/вложения (если сообщение моложе 24 часов)

Да, это «карусель для бедных». Зато без магии.

Загрузка медиа, отправка файлов и голосовых

Шаг 1: получить URL

curl -sS -X POST "https://platform-api.max.ru/uploads?type=file" \
-H "Authorization: ${MAX_BOT_TOKEN}"

Шаг 2: загрузить по URL (multipart)

curl -sS -X POST "%UPLOAD_URL%" \
-H "Authorization: ${MAX_BOT_TOKEN}" \
-F "data=@report.pdf"

Шаг 3: отправить сообщение с вложением (конкретный payload зависит от ответа загрузки; ключевой контракт - вложение с type и payload из ответа)

Для «голосовых» в Bot API явно выделенного voice-типа не показано, но есть type=audio для загрузки и sending_audio как чат-экшен - то есть практично отправлять голосовое как аудио-вложение.

И ещё один нюанс, который экономит часы жизни:

  • после загрузки файл может ещё обрабатываться; если отправить сразу - можно получить attachment.not.ready; рекомендация - пауза и повтор с увеличением интервала, или заранее загрузить и переиспользовать token.

Редактирование и удаление сообщений

Редактирование (cURL)

curl -sS -X PUT "https://platform-api.max.ru/messages?message_id=mid_123" \
-H "Authorization: ${MAX_BOT_TOKEN}" \
-H "Content-Type: application/json" \
-d '{ "text": "Изменённый текст", "format": "markdown" }'

Удаление (cURL)

curl -sS -X DELETE "https://platform-api.max.ru/messages?message_id=mid_123" \
-H "Authorization: ${MAX_BOT_TOKEN}"

Ограничение: и редактирование, и удаление - только для сообщений «моложе 24 часов». Это важно для любых «workflow-ботов», которые хотят править старые статусы.

Сравнение с Telegram и WhatsApp по API-интеграциям

Сразу договоримся: сравнение ниже про API и интеграцию, а не про «какой мессенджер кому нравится».

Доступ к API и онбординг

Макс

  • боты создаются через платформу для партнёров, есть модерация, токен появляется после одобрения.
  • доступ к платформе ограничен (юрлица/ИП, условия входа).

Telegram

  • Bot API - HTTP-based интерфейс для ботов.
  • лимиты рассылок и поведение при их превышении описаны очень прямо (и да, 429 там тоже часть жизни).

WhatsApp

  • бизнес-платформа завязана на Graph API и бизнес-идентификаторы (phone number id), а отправка идёт через /PHONE_NUMBER_ID/messages.
  • ограничения «шаблоны вне окна» - часть продукта: шаблоны можно отправлять вне customer service window, но они должны быть заранее одобрены.

Webhooks и polling

Макс

  • Webhook и Long Polling есть, но одновременно использовать нельзя; production рекомендуют на Webhook.
  • Webhook только HTTPS, есть секрет в заголовке.

Telegram

  • поддерживает и webhook, и long polling (это базовая архитектура Bot API).

WhatsApp

  • webhooks - основной механизм входящих событий и статусов (delivery/read и т.д.).

Группы и каналы

Макс

  • групповые чаты в API есть (/chats, права админов, участники, действия).
  • про каналы: создание/ведение каналов описано, но публикация контента заявлена как функция интерфейса клиента, а не публичного API.

Telegram

  • боты могут получать сообщения из каналов, где они являются участниками.
  • Bot API позволяет обращаться к каналам по @channelusername в параметре chat_id во многих методах (например, editMessageText).

WhatsApp

  • классический WhatsApp Business Messaging API ориентирован на 1:1 сообщения (в официальных гайдах это постоянно прослеживается).

Мультимедиа и хранение

Макс

  • upload выдаёт URL, поддерживает resumable upload, есть 4 ГБ лимит для multipart и отдельная стадия обработки после загрузки.

Telegram

  • у Bot API есть своя модель файлов/file_id и отдельная загрузка, но главное для интегратора - зрелая инфраструктура и предсказуемость контрактов.

WhatsApp

  • медиа и интерактивы есть, статусы доставки и чтения возвращаются вебхуками.

Шифрование и безопасность как фактор интеграции

Тут важный момент: мы обсуждаем не «кто лучше», а какие риски ты обязан закладывать в интеграцию.

WhatsApp

  • публично заявляет end-to-end encryption для сообщений и между людьми, и с бизнесами (Signal protocol).

Telegram

  • end-to-end encryption относится к Secret Chats, где ключи у участников, и это описано в официальной документации.
  • боты в секретные чаты не приглашаются (техническое ограничение).

Макс

  • в официальной Bot API документации я не увидел раздела, который бы утверждал наличие E2E шифрования для пользовательских чатов. При отсутствии такого заявления безопаснее проектировать интеграцию как server-side: считать, что контент обрабатывается на стороне платформы. (Это рекомендация.)
  • в публичных медиа много раз утверждалось, что сквозного шифрования нет (например, Forbes, январь 2026). Это не первоисточник платформы, но как риск-сигнал для интегратора - полезно учесть.

Безопасность, устойчивость, мониторинг и checklist внедрения

Типовые ошибки и как их пережить

HTTP-ошибки

  • 401 - токен неверный/отозван (или вы забыли заголовок Authorization).
  • 429 - превысили лимит запросов. Решение: глобальный rate limiter + backoff.
  • 503 - сервис недоступен. Решение: retry с backoff, но с верхним пределом и алёртом (иначе вы «вечно ретраите» и не знаете, что всё умерло).

Прикрепление медиа

  • attachment.not.ready - классика. Решение: ждать, ретраить, переиспользовать token/прегруз.

Webhook-доставка

  • контракт ретраев webhook со стороны Макс публично не описан - значит, считаем доставку как минимум «at-least-once» и делаем idempotency сами. Основание здесь косвенное: наличие webhook и общий паттерн индустрии, плюс запрет на одновременный polling.

Best practices, которые реально окупаются

  • Храните BOT_TOKEN только в secret manager, не в .env на проде и не в логах. Документация прямо говорит, что токен - прямой доступ к боту.
  • Для webhook:проверка X-Max-Bot-Api-Secret обязательна
    ответ 200 как можно быстрее, бизнес-логика в очередь
    логируйте update_type, mid, callback_id, latency обработчика.
  • Для long polling:храните marker durably
    обновляйте marker только после успешной обработки пачки.
  • Для медиа:делайте pre-upload популярных файлов и кешируйте token
    закладывайте задержку на обработку
    если файл критичен, делайте «проверочную отправку» в тестовый чат при деплое.
  • Для мини-приложений:валидируйте initData по HMAC (иначе любой «нарисует» себе пользователя)
    ставьте CSP и урезайте внешние источники
    не доверяйте initDataUnsafe для авторизации.

Советы по тестированию и отладке

  • Локальная разработка под webhook упирается в HTTPS. Документация запрещает HTTP, но разрешает самоподписанные сертификаты - значит, можно поднять локальный endpoint на HTTPS и пробросить наружу через туннель/реверс-прокси, главное - попасть в разрешённые порты.
  • Делайте отдельный «тестовый бот» и отдельный «тестовый чат» - в Макс это особенно актуально, потому что редактирование/удаление ограничены 24 часами и иначе вы быстро упрётесь в «Почему оно не обновилось?».
  • Для регресса API держите контрактные тесты на:GET /me
    POST /messages
    POST /subscriptions (и проверку заголовка секрета)
    POST /uploads (и полный цикл).

Checklist внедрения интеграции

Доступ

Организация верифицирована на партнёрской платформе и имеет право создавать ботов.
Бот прошёл модерацию, получен токен, настроена ротация токена.

Инфраструктура

Есть публичный HTTPS endpoint на разрешённом порту для webhook.
Настроен WAF/ingress и rate limiting со стороны вашей инфраструктуры (чтобы не стать «отражателем» чужих атак).

Безопасность

Проверяется X-Max-Bot-Api-Secret.
Секреты и токены не логируются, не попадают в трассировки, не утекают в клиент.

Надёжность

Реализован dedup (idempotency) по mid/callback_id и safe retries на 429/503.
Реализован глобальный лимитер под 30 rps на platform-api.max.ru.
Для медиа заложены ожидание обработки и ретраи на attachment.not.ready.

Функциональность

Поддержаны: входящие сообщения (webhook или polling), исходящие сообщения, кнопки/callback, загрузка файлов, редактирование/удаление (с учетом окна 24ч).
Отдельно зафиксировано: «публикация в канал через API» - неуточнено публично, требуется подтверждение способа адресации канала и прав бота.