--- url: 'https://docs.maxbotstat.ru/guide/getting-started.md' description: >- Что такое MaxBotStat, какие задачи решает и как подключить бота за две минуты — заменой базового адреса API в одной строке кода. --- # Что такое MaxBotStat MaxBotStat — это аналитика и автоматизация для **Telegram- и Max-ботов**. Платформа работает в режиме **прозрачного зеркала API**: вы оставляете весь код бота как есть и меняете в нём только один параметр — базовый адрес API. Запросы вашего бота идут не сразу в Telegram, а через наш домен, который пересылает их дальше и попутно сохраняет аналитику. ``` api.telegram.org → api-tg.app.maxbotstat.ru platform-api.max.ru → api-max.app.maxbotstat.ru ``` В отличие от закрытых конструкторов, MaxBotStat **ничего не переписывает** в логике вашего бота. Он по-прежнему сам обрабатывает входящие сообщения — на Node.js, Python, Go, PHP, через `getUpdates` или вызов на ваш сервер. Мы только посередине между ботом и Telegram. ## Что вы получаете * хранилище контактов с метаданными Telegram/Max и изображениями профиля; * историю сообщений и диалогов в реальном времени; * разметку трафика по UTM (параметр `utm_source` в команде `/start`); * воронки и автоматическую категоризацию сообщений (намерения); * массовые рассылки с медиа и сегментацией; * открытый API для интеграции с CRM и BI; * подписки на события `message.created`, `message.outbound`, `contact.created`. ## Кому подойдёт | Сценарий | Что даёт MaxBotStat | | --- | --- | | Маркетинговый бот в Telegram | разметка UTM, воронки, рассылки, выгрузка контактов | | Бот поддержки на Python | история диалогов, метки намерений, ответы из веб-кабинета | | Несколько ботов компании | единое хранилище контактов и аналитика по каждому из них | | Интеграция с CRM или BI | открытый API + подписки на события | | Замена закрытому облачному сервису | собственное хранилище данных, выгрузка, прозрачное зеркало | ## Быстрый старт за две минуты ### 1. Регистрация Откройте [app.maxbotstat.ru](https://app.maxbotstat.ru), создайте аккаунт и подтвердите почту шестизначным кодом из письма. ### 2. Привязка бота В кабинете нажмите **Добавить бота**, выберите платформу (Telegram или Max) и введите токен: * Telegram-токен берётся в [@BotFather](https://t.me/BotFather) после команды `/newbot`. * Max-токен — в кабинете [Max Business](https://business.max.ru/). ### 3. Замена адреса API в коде бота В коде своего бота замените базовый адрес API на наш домен: ```diff - https://api.telegram.org + https://api-tg.app.maxbotstat.ru ``` Большинство популярных библиотек поддерживают этот параметр напрямую. Например, для [Telegraf](https://telegraf.js.org/): ```js import { Telegraf } from 'telegraf' const bot = new Telegraf(process.env.BOT_TOKEN, { telegram: { apiRoot: 'https://api-tg.app.maxbotstat.ru' }, }) bot.start((ctx) => ctx.reply('Привет!')) bot.launch() ``` Полные примеры для [aiogram](/guide/connect#aiogram), [python-telegram-bot](/guide/connect#python-telegram-bot), [grammy](/guide/connect#grammy), [pyTelegramBotAPI](/guide/connect#pytelegrambotapi), [go-telegram-bot-api](/guide/connect#go-telegram-bot-api) и другие — в разделе [Замена адреса API в коде бота](/guide/connect). ## Что дальше * [Регистрация и вход](/guide/account) — что подтверждает почта, как восстанавливается доступ. * [Привязка бота](/guide/add-bot) — где взять токен Telegram, как привязать Max-бота. * [Замена адреса API в коде бота](/guide/connect) — примеры на популярных библиотеках. * [Открытый API](/api/overview) — для интеграции с CRM и BI. ::: tip Поддержка Вопросы — в раздел **«Поддержка»** в кабинете или на адрес команды. Сообщения видны и нам, и вам в одной ленте. ::: --- --- url: 'https://docs.maxbotstat.ru/guide/account.md' description: >- Как зарегистрировать аккаунт в MaxBotStat, подтвердить почту шестизначным кодом, войти и сменить пароль. --- # Регистрация и вход ## Регистрация 1. Откройте [app.maxbotstat.ru](https://app.maxbotstat.ru). 2. Нажмите **Регистрация**. Введите адрес почты и пароль не короче **6 символов**. 3. На указанный адрес уйдёт письмо с **шестизначным кодом подтверждения**. В кабинете появится поле «Код из письма». 4. Введите код — аккаунт активируется, вы автоматически попадёте в кабинет. ::: warning Подтверждение почты обязательно Без подтверждения адреса вы не сможете привязать бота и выпускать ключи API. Если письмо не пришло, нажмите «Отправить код повторно». Проверьте папку «Спам». ::: ## Вход * Адрес почты и пароль. * Сессия в браузере живёт 7 дней. После — повторный вход. * Можно войти на нескольких устройствах одновременно. ## Восстановление пароля В текущем выпуске поддерживается: * **Смена пароля изнутри кабинета** (если вы вошли). * **Сброс через поддержку**: напишите в раздел поддержки или администратору, доступ восстановят вручную. ## Удаление аккаунта Удаление аккаунта выполняется администратором. При этом: * бот деактивируется (новые запросы через наш домен возвращают ошибку); * история контактов и сообщений сохраняется до окончательной чистки; * адрес почты освобождается — на него можно зарегистрироваться заново. ## Роли | Роль | Что даёт | | --- | --- | | `user` | привязывает ботов, настраивает воронки, рассылки, выпускает ключи API | | `admin` | видит список всех пользователей, тарифы, отвечает в обращениях поддержки | При регистрации присваивается `user`. Повышение до `admin` делает существующий администратор системы. ## Командный доступ На тарифе **Макс** в одном аккаунте могут работать **до 10 человек**: владелец и до девяти приглашённых. Внутри одного аккаунта все участники видят одни и те же боты, диалоги, рассылки и аналитику. Роли участника команды: | Роль | Что может | | --- | --- | | Владелец | всё, плюс управление командой, тарифом и счетами | | Администратор | настраивать ботов, слать сообщения и рассылки, управлять API-ключами | | Наблюдатель | только просмотр аналитики и списков | Подробнее — на отдельной странице [Команда](./team). ## Войти под пользователем Администратор может временно «войти под пользователем» — это нужно для воспроизведения проблем. В кабинете это кнопка **Войти под пользователем** в списке пользователей. Возврат — кнопка **Выйти из режима** в верхней панели. --- --- url: 'https://docs.maxbotstat.ru/guide/add-bot.md' description: >- Как создать бота в @BotFather для Telegram или получить ключ доступа Max и привязать его к MaxBotStat в кабинете. --- # Привязка бота После регистрации и подтверждения почты можно привязывать бота. Поддерживаются две платформы: **Telegram** и **Max**. ## Telegram ### 1. Создайте бота в [@BotFather](https://t.me/BotFather) ``` /newbot > MyShop bot > myshop_bot ``` `@BotFather` пришлёт сообщение с токеном вида: ``` 123456789:AAH4xExampleTokenStringFromBotFather_ABC ``` ::: danger Сохраните токен Токен — это пароль бота. Никому его не передавайте, не публикуйте в репозитории. В MaxBotStat токен хранится в зашифрованном виде и никогда не возвращается через API. ::: ### 2. Привяжите бота в кабинете 1. На главной кабинета нажмите **Добавить бота**. 2. Выберите платформу **Telegram**. 3. Введите название (для вас) и токен. 4. Нажмите **Сохранить**. MaxBotStat автоматически: * проверит токен через `getMe`; * сохранит имя, username и изображение профиля бота. ### 3. Замените адрес API в коде бота В коде своего бота поменяйте базовый адрес Telegram Bot API: ```diff - https://api.telegram.org + https://api-tg.app.maxbotstat.ru ``` Все методы остаются прежними — мы прозрачно передаём запросы дальше в Telegram. Подробные примеры на популярных библиотеках — в разделе [Замена адреса API в коде бота](/guide/connect). ## Max [Max](https://max.ru) — мессенджер от VK. У ботов Max есть API, аналогичный по структуре Telegram. ### 1. Получите ключ доступа 1. Создайте бота в [Max Business](https://business.max.ru/). 2. Скопируйте `access_token`. ### 2. Привяжите в кабинете То же самое, что для Telegram, но платформа — **Max**. ### 3. Замените адрес API В коде Max-бота замените: ```diff - https://platform-api.max.ru + https://api-max.app.maxbotstat.ru ``` ## Без токена Бот можно привязать и **без токена**, но тогда вы не сможете: * отправлять рассылки и одиночные сообщения от имени бота из кабинета; * получать изображения профиля контактов автоматически; * использовать `POST /api/v1/.../send` и `POST /api/v1/.../broadcast`. Это сценарий «только аналитика» — годится, если вам нужно лишь видеть переписку и статистику, а отвечает бот сам со своего сервера. ## Лимиты * Один пользователь — до **20 ботов** одновременно. * На один токен Telegram/Max можно привязать только одного бота в системе. * Лимит ключей API на пользователя — **20 активных**. --- --- url: 'https://docs.maxbotstat.ru/guide/connect.md' description: >- Как заменить базовый адрес Telegram Bot API и Max API на MaxBotStat в популярных библиотеках — Telegraf, grammy, aiogram, python-telegram-bot, pyTelegramBotAPI, go-telegram-bot-api и других. --- # Замена адреса API в коде бота Чтобы MaxBotStat начал собирать аналитику и работать как зеркало API, в коде вашего бота достаточно поменять один параметр — **базовый адрес API**. | Платформа | Было | Стало | | --- | --- | --- | | Telegram | `https://api.telegram.org` | `https://api-tg.app.maxbotstat.ru` | | Max | `https://platform-api.max.ru` | `https://api-max.app.maxbotstat.ru` | Все методы остаются прежними — `getMe`, `sendMessage`, `getUpdates`, `setWebhook` и так далее. Меняется только домен. Ниже — примеры на популярных библиотеках. ## Telegraf {#telegraf} [Telegraf](https://telegraf.js.org/) — самая популярная Telegram-библиотека для Node.js. Параметр называется `apiRoot`: ```js import { Telegraf } from 'telegraf' const bot = new Telegraf(process.env.BOT_TOKEN, { telegram: { apiRoot: 'https://api-tg.app.maxbotstat.ru' }, }) bot.start((ctx) => ctx.reply('Привет!')) bot.launch() ``` ## grammy {#grammy} [grammY](https://grammy.dev/) — современная Telegram-библиотека для Node.js и Deno. Параметр называется `apiRoot`: ```ts import { Bot } from 'grammy' const bot = new Bot(process.env.BOT_TOKEN!, { client: { apiRoot: 'https://api-tg.app.maxbotstat.ru' }, }) bot.command('start', (ctx) => ctx.reply('Привет!')) bot.start() ``` ## node-telegram-bot-api {#node-telegram-bot-api} [node-telegram-bot-api](https://github.com/yagop/node-telegram-bot-api) — старейшая библиотека для Node.js. Параметр называется `baseApiUrl`: ```js import TelegramBot from 'node-telegram-bot-api' const bot = new TelegramBot(process.env.BOT_TOKEN, { polling: true, baseApiUrl: 'https://api-tg.app.maxbotstat.ru', }) bot.onText(/\/start/, (msg) => { bot.sendMessage(msg.chat.id, 'Привет!') }) ``` ## python-telegram-bot {#python-telegram-bot} [python-telegram-bot](https://docs.python-telegram-bot.org/) — официальная и самая распространённая библиотека для Python. Параметр называется `base_url`: ```python from telegram.ext import Application, CommandHandler async def start(update, context): await update.message.reply_text("Привет!") app = ( Application.builder() .token(os.environ["BOT_TOKEN"]) .base_url("https://api-tg.app.maxbotstat.ru/bot") .base_file_url("https://api-tg.app.maxbotstat.ru/file/bot") .build() ) app.add_handler(CommandHandler("start", start)) app.run_polling() ``` ::: tip Хвостик `/bot` обязателен Здесь библиотека сама добавляет токен и метод после префикса, поэтому в `base_url` нужно передавать адрес **с суффиксом `/bot`** (а в `base_file_url` — с `/file/bot`). ::: ## aiogram {#aiogram} [aiogram](https://docs.aiogram.dev/) — асинхронная Telegram-библиотека для Python. Адрес задаётся через объект `TelegramAPIServer`: ```python import asyncio from aiogram import Bot, Dispatcher, types from aiogram.client.session.aiohttp import AiohttpSession from aiogram.client.telegram import TelegramAPIServer API_BASE = "https://api-tg.app.maxbotstat.ru" session = AiohttpSession(api=TelegramAPIServer.from_base(API_BASE)) bot = Bot(token=os.environ["BOT_TOKEN"], session=session) dp = Dispatcher() @dp.message() async def echo(message: types.Message): await message.answer("Привет!") asyncio.run(dp.start_polling(bot)) ``` ## pyTelegramBotAPI (telebot) {#pytelegrambotapi} [pyTelegramBotAPI](https://pytba.readthedocs.io/) — простая синхронная библиотека для Python. Адрес задаётся через `apihelper.API_URL`: ```python import telebot from telebot import apihelper apihelper.API_URL = "https://api-tg.app.maxbotstat.ru/bot{0}/{1}" apihelper.FILE_URL = "https://api-tg.app.maxbotstat.ru/file/bot{0}/{1}" bot = telebot.TeleBot(os.environ["BOT_TOKEN"]) @bot.message_handler(commands=["start"]) def start(message): bot.reply_to(message, "Привет!") bot.infinity_polling() ``` ## go-telegram-bot-api {#go-telegram-bot-api} Библиотека [go-telegram-bot-api](https://github.com/go-telegram-bot-api/telegram-bot-api) для Go. Метод называется `SetAPIEndpoint`: ```go package main import ( "log" "os" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) func main() { bot, err := tgbotapi.NewBotAPI(os.Getenv("BOT_TOKEN")) if err != nil { log.Fatal(err) } bot.SetAPIEndpoint("https://api-tg.app.maxbotstat.ru/bot%s/%s") upd := tgbotapi.NewUpdate(0) upd.Timeout = 60 for u := range bot.GetUpdatesChan(upd) { if u.Message != nil { msg := tgbotapi.NewMessage(u.Message.Chat.ID, "Привет!") bot.Send(msg) } } } ``` ## telebot.v3 (Go, gopkg.in/telebot.v3) {#telebot-go} ```go package main import ( "os" tele "gopkg.in/telebot.v3" ) func main() { bot, _ := tele.NewBot(tele.Settings{ Token: os.Getenv("BOT_TOKEN"), URL: "https://api-tg.app.maxbotstat.ru", }) bot.Handle("/start", func(c tele.Context) error { return c.Send("Привет!") }) bot.Start() } ``` ## PHP — telegram-bot-sdk {#php-telegram-bot-sdk} [telegram-bot-sdk](https://telegram-bot-sdk.readthedocs.io/) для PHP/Laravel. Параметр в конфиге называется `base_bot_url`: ```php use Telegram\Bot\Api; $bot = new Api(getenv('BOT_TOKEN')); $bot->setBaseBotUrl('https://api-tg.app.maxbotstat.ru/bot'); $bot->sendMessage([ 'chat_id' => 123456789, 'text' => 'Привет!', ]); ``` ## cURL и любой HTTP-клиент {#curl} Если используете «голые» HTTP-запросы — просто меняйте домен: ```bash # было curl "https://api.telegram.org/bot$BOT_TOKEN/getMe" # стало curl "https://api-tg.app.maxbotstat.ru/bot$BOT_TOKEN/getMe" ``` То же касается `fetch`, `axios`, `requests`, `http.Client`, `Guzzle` и любого другого клиента. Все методы и формат запросов идентичны Telegram Bot API. ## Max-боты Для Max-ботов меняется домен `https://platform-api.max.ru` на `https://api-max.app.maxbotstat.ru`: ```js const MAX = 'https://api-max.app.maxbotstat.ru' const r = await fetch(`${MAX}/messages?chat_id=${chatId}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': process.env.MAX_TOKEN, }, body: JSON.stringify({ text: 'Привет!' }), }) ``` ## Что после замены адреса Сразу после первой команды от пользователя: * в кабинете в разделе **Контакты** появится новый собеседник; * в **Диалогах** — лента сообщений; * если в `/start` был параметр `utm_source` — в разделе **Источники** запишется значение. Никаких дополнительных шагов не требуется — статистика собирается автоматически с каждого запроса вашего бота. ## Безопасность * Все обращения к нашему домену идут по HTTPS (сертификат Let's Encrypt с автообновлением, TLS 1.2 и 1.3). * Токен бота никуда не сохраняется — он передаётся в адресе так же, как при прямом обращении к Telegram. * Тела запросов и ответов не попадают в долгосрочное хранилище: мы извлекаем из них факты для аналитики (контакт, текст, идентификатор сообщения) и забываем тело. ## Ограничения * Размер тела запроса — до 50 МБ (как у Telegram). * Прокси не повторяет запросы при тайм-ауте — повтор делайте в своём клиенте. * Все ограничения частоты Telegram (30 запросов в секунду на бота, 1 в секунду в один диалог) сохраняются. ## Откатиться Если нужно временно отключить аналитику и работать напрямую с Telegram — просто верните в коде старый адрес `https://api.telegram.org`. Бот в кабинете при этом сохранится, новые сообщения перестанут поступать. Когда вернёте наш домен — аналитика возобновится. --- --- url: 'https://docs.maxbotstat.ru/guide/contacts.md' description: >- Раздел контактов в MaxBotStat — фильтры, метаданные пользователя, изображения профиля, история диалогов и поиск. --- # Контакты и диалоги В разделе **Контакты** живёт всё, что бот узнал о собеседниках, которые ему писали хоть раз. ## Что записывается | Поле | Источник | | --- | --- | | `external_user_id` | `from.id` из обновления Telegram / Max | | `username` | `from.username` | | `first_name`, `last_name` | `from.first_name`, `from.last_name` | | `is_premium` | `from.is_premium` (Telegram Premium) | | `language_code` | `from.language_code` | | `phone` | если пользователь поделился контактом | | `last_seen_at` | время последнего входящего сообщения | | `source_value` | значение UTM (если был параметр в `/start`) | | `campaign_name` | название кампании (см. [Источники по UTM](/guide/sources)) | ## Изображения профиля MaxBotStat подгружает аватар Telegram через `getUserProfilePhotos` и `getFile` (или соответствующий метод Max). Изображения отдаются через **наш сервер**: ``` GET /api/avatars/contact// ``` Это сделано, чтобы: * не показывать токен бота в браузере; * избежать смешанного содержимого (Telegram CDN не всегда отдаёт изображения по HTTPS); * кешировать ответ (живёт 60 минут). ## Диалоги Раздел **Диалоги** показывает контакты в порядке последнего сообщения — как мессенджер. Кликаете по контакту → открывается полная история переписки (входящие и исходящие со стрелочками). ## Поиск Сверху списка — поле поиска. Ищем по: * `username`; * имени и фамилии; * `external_user_id`; * содержанию последнего сообщения. Поиск работает по подстроке, регистр не важен. ## Карточка контакта В карточке контакта вы увидите: * метаданные пользователя; * источник (UTM) и кампанию; * общее число сообщений (входящих и исходящих); * сработавшие намерения (если настроены); * кнопку **Написать** — отправить сообщение от имени бота. ## Через открытый API ```bash curl "https://app.maxbotstat.ru/api/v1/bots//contacts?limit=100&offset=0" \ -H "X-API-Key: mbs_..." ``` Полная схема ответа: [API → Контакты](/api/contacts). ## Обновление в реальном времени Кабинет MaxBotStat обновляет ленту диалогов в реальном времени по веб-сокетам. Если делаете собственный кабинет — подпишитесь на событие `message.created` и обновляйте состояние у себя. См. [Подписка на события](/api/webhooks). --- --- url: 'https://docs.maxbotstat.ru/guide/messages.md' description: >- Раздел «Сообщения» в кабинете MaxBotStat — фильтры по дате и пользователю, графики активности, выгрузка. --- # Сообщения и активность ## Лента сообщений Раздел **Сообщения** показывает все обновления, прошедшие через наш домен: * `direction: in` — пользователь → бот; * `direction: out` — бот → пользователь (отправка из кабинета, рассылка или вызов открытого API). Колонки: | Колонка | Что показывает | | --- | --- | | Время | `created_at` (UTC) | | Контакт | `username` или имя и фамилия, кликабельно — открывает диалог | | Текст | первые 200 символов сообщения | | Источник | значение UTM контакта | | Бот | если ботов несколько и фильтр выключен | ## Фильтры * **Период**: за сегодня, 7 / 30 / 90 дней или произвольный диапазон. * **Бот**: один бот или все. * **Направление**: входящие / исходящие / оба. * **Пользователь**: по `external_user_id` или `username`. ## График активности Вкладка **Активность** показывает графики: * сообщения по дням (входящие и исходящие); * новые контакты; * активные пользователи (минимум одно сообщение за период). Источник данных — метод `GET /api/v1/bots//stats/timeline`. См. [API → Статистика](/api/stats). ## Выгрузка Сейчас выгрузка сообщений делается через открытый API: ```bash curl "https://app.maxbotstat.ru/api/v1/bots//messages?from=2025-01-01&to=2025-12-31&limit=1000" \ -H "X-API-Key: mbs_..." \ -o messages.json ``` Параметры: * `from`, `to` — границы по `created_at` (формат `YYYY-MM-DD` или ISO 8601); * `userId` — фильтр по конкретному пользователю; * `limit` — до 1000 за один запрос (используйте постраничную выборку). ## Связь с исходным обновлением Каждое сообщение в базе хранит исходное обновление Telegram/Max в поле `raw_json`. Через открытый API оно не возвращается (для экономии трафика), но видно в режиме отладки и используется при ручном разборе случаев. --- --- url: 'https://docs.maxbotstat.ru/guide/sources.md' description: >- Как разметить трафик в Telegram-боте через параметр /start, настроить ключ UTM и сопоставить значения с кампаниями в MaxBotStat. --- # Источники по UTM UTM в боте работает не так, как в вебе — там нет адреса с параметрами. В Telegram параметр передаётся в команде `/start`: ``` https://t.me/your_bot?start=instagram ``` Telegram вставит этот параметр в первое сообщение пользователя: ``` /start instagram ``` MaxBotStat умеет это разбирать и сохранять как **источник** контакта. ## Настройка ключа UTM По умолчанию ключ — `utm_source`, но это меняется. Зайдите в **Настройки бота → Источники**: ``` ключ = source → /start source=instagram ключ = utm_source → /start utm_source=instagram ``` Допустимые форматы стартового параметра: | Формат | Пример | Разберётся как | | --- | --- | --- | | просто значение | `/start instagram` | `source_value=instagram` | | `ключ=значение` | `/start utm_source=instagram` | `source_value=instagram` (если ключ — `utm_source`) | | несколько ключей | `/start utm_source=ig\|utm_campaign=spring` | `source_value=ig`, `campaign_name=spring` | ::: tip Поддерживаются разделители `|` и `&` для нескольких пар. Регистр значений сохраняется как есть. ::: ## Сопоставления Можно нормализовать источники: например, превратить `ig`, `Instagram`, `instagram_main` в одно значение `Instagram`. В разделе **Источники** добавьте сопоставление: ``` исходное значение: ig нормализованное: Instagram кампания: Spring sale ``` После этого в отчётах все три варианта схлопнутся в `Instagram` / `Spring sale`. ## Где смотреть * **Раздел «Источники»** — таблица: источник, число контактов, сумма касаний, последний контакт. * **Карточка контакта** — индивидуальный источник и кампания. * **Открытый API** — `GET /api/v1/bots//sources`. ## Через открытый API ```bash curl "https://app.maxbotstat.ru/api/v1/bots//sources" \ -H "X-API-Key: mbs_..." ``` ```json { "utm_key": "utm_source", "data": [ { "source_value": "instagram", "campaign_name": "spring", "contacts_count": 412, "touches": 1024 }, { "source_value": "ads", "campaign_name": null, "contacts_count": 88, "touches": 162 }, { "source_value": "— unmapped","campaign_name": null, "contacts_count": 5, "touches": 12 } ] } ``` `— unmapped` — это контакты, у которых не было `/start` с параметром (зашли напрямую через диалог). ## Полезные ссылки * [Telegram Bot API → глубокие ссылки](https://core.telegram.org/api/links#bot-link) * [Воронки](/guide/funnel) — анализ конверсии по этапам пути. --- --- url: 'https://docs.maxbotstat.ru/guide/funnel.md' description: >- Как настроить воронку этапов в MaxBotStat — фильтры по тексту и намерениям, расчёт конверсии и наглядное представление. --- # Воронки Воронка — это упорядоченный список «этапов», по которым проходит пользователь. Например: 1. Пришёл по `/start`. 2. Дошёл до выбора тарифа. 3. Оплатил. MaxBotStat считает, сколько контактов добралось до каждого этапа, и показывает конверсию. ## Этапы Этап описывается **условием на сообщение**. Поддерживаются: * **Текст**: точное совпадение или подстрока. * **Команда**: `/start`, `/help`, `/buy`. * **Намерение**: пользователь сказал что-то, что попадает в категорию (см. [Намерения](/guide/intents)). Пример воронки «Покупка тарифа Pro»: | № | Название | Условие | | --- | --- | --- | | 1 | Старт | команда `/start` | | 2 | Открыл каталог | намерение `catalog` | | 3 | Выбрал тариф Pro | текст содержит `pro` | | 4 | Подтвердил оплату | намерение `payment_confirm` | ## Настройка **Бот → Воронки → Создать воронку.** Дайте имя, добавьте этапы по одному. Каждое условие срабатывает на входящих сообщениях (`direction='in'`). ## Расчёт MaxBotStat для каждого контакта проверяет: 1. было ли у него хоть одно сообщение, удовлетворяющее условию этапа N; 2. если да — он считается «дошедшим» до этапа N. Конверсия N → N+1 = `count(дошёл до N+1) / count(дошёл до N)`. ::: tip Порядок имеет значение: «дошёл до 3» неявно означает «прошёл 1 и 2». В кабинете вы увидите наглядную воронку с уменьшающимся «горлышком». ::: ## Открытый API Конфигурация воронки и расчёт доступны через закрытые методы кабинета (с сессионным ключом): ``` GET /api/bots/:id/funnel/config PUT /api/bots/:id/funnel/config GET /api/bots/:id/funnel ``` В открытом API `/api/v1/...` воронок пока нет — данные считаются по закрытому API кабинета. ## Что попадает в шаги * **Только входящие сообщения**. Ответы бота не считаются «прохождением этапа». * Время прохождения этапа = время первого подходящего сообщения. * Если пользователь повторно «прошёл» этап (написал то же самое второй раз) — это **не** считается ещё раз. ## Связь с UTM Воронку можно фильтровать по источнику в кабинете: «конверсия пользователей с `utm_source=instagram`». Полезно для сравнения каналов трафика. --- --- url: 'https://docs.maxbotstat.ru/guide/intents.md' description: >- Как описать намерение в MaxBotStat — ключевые слова и регулярные выражения, использовать для воронок и сегментации рассылок. --- # Намерения **Намерение** — это категория, в которую MaxBotStat относит входящее сообщение. Например: * `greeting` — пользователь поздоровался; * `payment` — спросил про оплату; * `complaint` — выразил недовольство; * `support_request` — попросил помощь. Назначение — двигатель сегментации: * **Воронки**: этап «дошёл до оплаты» = намерение `payment`. * **Рассылка**: только тем, у кого было намерение `complaint`. * **Аналитика**: топ-категории, динамика во времени. ## Создание намерения **Бот → Намерения → Создать.** Поля: | Поле | Описание | | --- | --- | | Имя | технический ключ (без пробелов) | | Описание | для команды | | Цвет | для подсветки в кабинете | | Активно | можно временно выключить | | Правила | условия срабатывания | ## Правила Поддерживаются: * **Ключевые слова** (по подстроке без учёта регистра): `оплат`, `купить`, `тариф`. * **Регулярные выражения**: `^/start( |$)`, `\d{4,}`. * **Точное совпадение**: команда `/buy`. Несколько правил в одном намерении — соединены логическим «или». Несколько намерений в проекте — каждое сообщение может попасть в **несколько** намерений одновременно. ## Применение После сохранения намерение применяется: * **к новым** сообщениям — сразу при их поступлении; * **к историческим** — через ручную пересборку (кнопка «Пересчитать» в кабинете). ## Сводка В разделе **Сводка намерений**: * сколько контактов попало в каждое намерение; * сколько сообщений; * топ-сообщения, сработавшие на правило (для проверки качества). ## Открытый API ```bash curl "https://app.maxbotstat.ru/api/v1/bots//intents" \ -H "X-API-Key: mbs_..." ``` ```json { "data": [ { "id": "67d4...", "name": "payment", "description": "Вопросы про оплату", "color": "#16a34a", "is_active": true, "users_count": 312, "messages_count": 845, "created_at": "2025-09-01T10:00:00Z" } ] } ``` ## Рекомендации * Не плодите намерения — лучше 5–7 широких категорий, чем 50 узких. * Давайте намерениям понятные имена (`payment_question`, не `i7`). * Регулярные выражения проверяйте на исторических данных перед включением. * Помните: один и тот же текст может попасть в несколько намерений — это часто полезно (`payment` + `complaint`). --- --- url: 'https://docs.maxbotstat.ru/guide/broadcast.md' description: >- Как отправить рассылку в MaxBotStat — текст, изображение, аудио, файл; ограничения Telegram, отчёт о доставке и открытый API. --- # Массовая рассылка MaxBotStat умеет отправлять одно и то же сообщение всем контактам бота — текстом или с медиа. ## Через кабинет 1. Откройте бота → **Рассылки** → **Создать**. 2. Введите текст (до 4000 знаков). 3. По желанию прикрепите файл: * **изображение** — JPG/PNG до 20 МБ; * **аудио** — MP3/M4A до 20 МБ; * **файл** — любой тип до 20 МБ. 4. Выберите платформу: все, только Telegram-боты или только Max. 5. Нажмите **Отправить**. После запуска вы увидите счётчик: **отправлено / не доставлено / всего**. Каждое исходящее сообщение записывается в базу с `direction='out'`. ## Ограничения и лимиты Telegram ставит жёсткие пределы на отправку: * **30 сообщений в секунду** на одного бота для разных пользователей; * **20 сообщений в минуту** в одну группу. * При превышении — ответ `429 Too Many Requests` с заголовком `Retry-After`. MaxBotStat **не разгоняет** рассылку искусственно: отправляем последовательно, пишем в `failed_count` каждый отказ. На 5000 контактов рассылка займёт несколько минут. ::: warning Если бот заблокирован пользователем (`Forbidden: bot was blocked by the user`) — это считается неудачной попыткой. Контакт остаётся в базе, но при следующих рассылках снова будет среди недоставленных. ::: ## Через открытый API ```bash curl -X POST "https://app.maxbotstat.ru/api/v1/bots//broadcast" \ -H "X-API-Key: mbs_..." \ -H "Content-Type: application/json" \ -d '{"text":"Привет! Скидка 20% по промокоду SPRING до конца недели."}' ``` Ответ: ```json { "id": "8c3a...", "total_count": 412, "sent_count": 408, "failed_count": 4, "created_at": "2026-04-30T12:00:00Z" } ``` Метод **синхронный** — вернётся, когда отправит всем. Для больших аудиторий используйте кабинет: там видно ход рассылки. ::: tip Защита от повтора Чтобы не повторить рассылку при повторном вызове, на стороне клиента храните `id` ответа. Повторный вызов создаст **новую** рассылку — система не делает автоматическое объединение. ::: ## Сегментация В кабинете можно ограничить аудиторию: * по источнику (UTM); * по намерению; * по дате последнего сообщения (например, «активные за 30 дней»). В открытом API рассылка идёт по **всем контактам** бота. Для сегментов используйте кабинет. ## Отчёты Все рассылки сохраняются в таблицу `broadcasts`: | Поле | Описание | | --- | --- | | `id` | публичный идентификатор | | `text` | текст рассылки | | `total_count` | сколько контактов было выбрано | | `sent_count` | сколько успешно доставлено | | `failed_count` | сколько не доставлено | | `created_at` | время старта | ## Этикет * Не шлите одно и то же сообщение чаще раза в неделю — растёт число недоставленных. * Используйте сегменты по намерениям, чтобы попадать в нужную аудиторию. * Не отправляйте холодным контактам — Telegram активно банит ботов с массовым спамом. --- --- url: 'https://docs.maxbotstat.ru/guide/send.md' description: >- Как отправить сообщение конкретному пользователю Telegram или Max через кабинет MaxBotStat и открытый API v1. --- # Одиночные сообщения В отличие от рассылки, одиночное сообщение адресовано **одному контакту**. Это полезно для поддержки и ответов на запросы. ## Из кабинета 1. **Контакты** → откройте карточку контакта. 2. Нажмите **Написать**. 3. Введите текст. Поддержки медиа в этом кабинете пока нет — для медиа используйте отправку через закрытый API. 4. Отправить. Сообщение придёт пользователю от имени бота и появится в **Диалогах** с `direction='out'`. ## Через открытый API ```bash curl -X POST "https://app.maxbotstat.ru/api/v1/bots//send" \ -H "X-API-Key: mbs_..." \ -H "Content-Type: application/json" \ -d '{"userId":"123456789","text":"Здравствуйте! Чем помочь?"}' ``` Параметры: | Поле | Тип | Описание | | --- | --- | --- | | `userId` | строка | `external_user_id` контакта (число — для Telegram, идентификатор — для Max) | | `text` | строка | текст сообщения, до 4000 знаков | Ответ: ```json { "ok": true, "id": "5d31...", "direction": "out", "text": "Здравствуйте! Чем помочь?", "created_at": "2026-04-30T15:23:01Z" } ``` Под капотом: * для Telegram — `POST /bot/sendMessage` с `chat_id=userId`; * для Max — `POST /messages?chat_id=` с заголовком `Authorization`. ## Отправка медиа В кабинете доступна отправка медиа через закрытый метод: ``` POST /api/bots/:id/send-media Content-Type: multipart/form-data Authorization: Bearer userId=123456 text=Прайс-лист file=@price.pdf kind=file ``` В открытом API этой возможности пока нет — отправка с медиа доступна только через рассылку (`/broadcast`) или закрытый API. ## Когда `userId` неизвестен Если у вас на руках только `username`, а `external_user_id` нет, нельзя написать первым: Telegram запрещает ботам инициировать диалог. Дождитесь, пока пользователь напишет `/start`, после чего `external_user_id` появится в контактах. ## Обработка ошибок | Код | Значение | | --- | --- | | `400 Bad Request` | пустой `text` или невалидный `userId` | | `404 Not Found` | бот не найден или не принадлежит вам | | `400 Personal send requires bot token` | у бота не указан токен — отправка невозможна | | `502 Bad Gateway` | Telegram/Max ответил ошибкой; в поле `provider` — детали | --- --- url: 'https://docs.maxbotstat.ru/guide/support.md' description: >- Система обращений в MaxBotStat — как создать обращение, прикрепить файлы, общаться с командой и получать уведомления на почту. --- # Поддержка В кабинете есть встроенная система обращений. Это удобнее, чем переписка по почте — у каждого обращения своя история, состояние и важность. ## Создать обращение 1. **Поддержка** → **Новое обращение**. 2. Тема (короткое описание) и текст. 3. Можно прикрепить до **5 файлов** (по 10 МБ каждый). 4. **Отправить.** Обращение получит идентификатор, состояние `open` и важность `normal`. Команде уйдёт уведомление на почту. ## Переписка Внутри обращения — лента сообщений. Любая сторона может отвечать, прикреплять файлы. Поддерживаются: * текст, эмодзи, переносы строк; * изображения (`image/png`, `image/jpeg`, `image/webp`, `image/gif`); * PDF, Word, Excel, ZIP. Когда команда отвечает — на почту пользователя приходит уведомление со ссылкой на обращение. ## Состояния | Состояние | Что значит | | --- | --- | | `open` | новое, ждёт ответа команды | | `pending` | команда ответила, ждёт реакции пользователя | | `closed` | обращение закрыто, обсуждение завершено | Закрыть может только команда, но пользователь может попросить. ## Важность `low` / `normal` / `high` / `urgent`. По умолчанию `normal`. Меняется только командой поддержки. ## Уведомления Уведомления на почту идут в трёх случаях: * команде — при создании обращения; * команде — при новом сообщении в обращении от пользователя; * пользователю — при новом сообщении в обращении от команды. ## Лимиты * максимум **5 файлов** на сообщение; * максимум **10 МБ** на файл; * размер обращения не ограничен (но история обрезается в кабинете первыми 200 сообщениями для скорости). ## Через открытый API Система обращений пока **только в закрытом API** кабинета (`/api/support/tickets/...` с сессионным ключом). Открытый API на постоянных ключах её не покрывает. Если у вас задача автоматизировать создание обращений из вашего сервера — используйте подписку на события: бот пишет → вы получаете уведомление → создаёте обращение на своей стороне. См. [Подписка на события](/api/webhooks). --- --- url: 'https://docs.maxbotstat.ru/guide/billing.md' description: >- Как устроены тарифы MaxBotStat, как оплатить через Robokassa и где смотреть текущий план. --- # Тарифы и оплата ::: info Ранний выпуск Тарификация в текущем выпуске — пробная. Лимиты могут меняться, действующие пользователи получают расширенный план на тестовой площадке по умолчанию. ::: ## Просмотр доступных тарифов В кабинете: **Настройки → Тарифы**. Также — открытый метод без авторизации: ```bash curl "https://app.maxbotstat.ru/api/plans" ``` Пример ответа: ```json [ { "key": "free", "name": "Бесплатный", "price_cents": 0, "currency": "RUB", "limits": { "bots": 1, "messages_per_month": 10000 } }, { "key": "pro", "name": "Pro", "price_cents": 49000, "currency": "RUB", "limits": { "bots": 10, "messages_per_month": 1000000 } } ] ``` `price_cents` — цена в копейках (49000 = 490 ₽). ## Текущий план пользователя ```bash curl "https://app.maxbotstat.ru/api/me/plan" \ -H "Authorization: Bearer " ``` ```json { "plan_key": "pro", "plan_until": "2026-06-01T00:00:00Z", "limits": { "bots": 10, "messages_per_month": 1000000 } } ``` `plan_until` — дата окончания. После этой даты — автоматический возврат на `free`. ## Оплата через Robokassa 1. **Тарифы → Оплатить.** Выберите план и срок (1 / 3 / 12 месяцев). 2. Кабинет создаст ссылку на оплату через [Robokassa](https://robokassa.com). 3. Оплатите (банковская карта, СБП, электронные деньги). 4. После ответного запроса от Robokassa MaxBotStat активирует план — обычно в течение 60 секунд. ## Возвраты и смена тарифа * Смена на более дорогой тариф — пропорциональная доплата за остаток текущего периода. * Смена на более дешёвый — действует со следующего периода. * Возврат — через поддержку, рассматривается индивидуально. ## Лимиты тарифа Если вы исчерпали лимит: * **Боты**: при достижении лимита нельзя добавить нового бота. * **Сообщения в месяц**: входящие и исходящие сообщения перестают сохраняться (зеркало возвращает ответ Telegram, но в базе пусто). * **Ключи API**: лимит активных — 20 на пользователя независимо от плана. После окончания месяца счётчик сообщений сбрасывается. ## Юридическим лицам Безналичная оплата по реквизитам — прямо из кабинета, без обращения в поддержку. 1. **Тарифы → выберите план** и срок (1 / 3 / 12 месяцев). 2. Нажмите **«Выставить счёт на N ₽»**. 3. Заполните данные организации в открывшейся форме: название, ИНН, КПП (если есть), юридический адрес, e-mail для отправки счёта. 4. Счёт приходит на указанный e-mail. PDF также доступен в разделе **«Счета»** в кабинете. 5. После поступления оплаты на расчётный счёт подписка активируется автоматически. Закрывающие документы (акт, УПД) приходят на ту же почту. История выставленных счётов и их статусы — в разделе **«Счета»**. --- --- url: 'https://docs.maxbotstat.ru/guide/team.md' description: >- Командный доступ в MaxBotStat — до 10 человек на тарифе «Макс». Приглашения по email, роли владельца, администратора и наблюдателя, переключение между аккаунтами. --- # Команда На тарифе **Макс** в одном аккаунте могут одновременно работать **до 10 человек**. Все участники видят одни и те же боты, диалоги, рассылки, статистику и счета — это общий рабочий аккаунт. На бесплатном тарифе и тарифах «Микро»/«Про» лимит участников — 1 (только владелец). Чтобы собрать команду, перейдите на «Макс». ## Роли | Роль | Управляет командой и счётом | Настраивает ботов и рассылки | Видит аналитику | | ------------- | :-------------------------: | :--------------------------: | :-------------: | | Владелец | ✓ | ✓ | ✓ | | Администратор | | ✓ | ✓ | | Наблюдатель | | | ✓ | Владелец у аккаунта один. Передать владение можно из карточки участника — текущий владелец станет администратором. ## Пригласить участника 1. В кабинете откройте раздел **Команда**. 2. Нажмите **Пригласить**, укажите email и роль. 3. На указанный адрес уйдёт письмо со ссылкой `?invite=`. Срок действия — **7 дней**. 4. Получатель регистрируется (или входит) под этим email и принимает приглашение. Слот резервируется в момент создания приглашения. Если слотов нет — приглашение не отправится: придётся отозвать чьё-то старое или повысить тариф. ## Принять приглашение Перейдите по ссылке из письма. Если вы не вошли — войдите или зарегистрируйтесь под адресом, на который пришло приглашение. Приглашения для другого email система не примет. ## Переключение между аккаунтами Если вы участник нескольких аккаунтов (например, свой собственный + чужой), в сайдбаре над переключателем ботов появится переключатель аккаунтов. Контекст хранится в `localStorage` (`mbs_account_id`) и передаётся в API заголовком `X-Account-Id`. Боты, статистика и API-ключи привязаны к аккаунту: при переключении кабинет полностью обновится. ## Удаление участника и выход * Владелец может удалить любого участника из карточки в разделе **Команда**. * Любой участник, кроме владельца, может покинуть аккаунт сам — кнопка **Покинуть аккаунт**. * Чтобы удалить аккаунт целиком (вместе с ботами), напишите в поддержку. ## Биллинг и счета Тариф и счета привязаны к аккаунту, а не к каждому участнику отдельно. Платит и видит счета только владелец — остальные участники работают, не вмешиваясь в оплату. --- --- url: 'https://docs.maxbotstat.ru/api/overview.md' description: >- Базовый адрес, авторизация, формат ответов и постраничная выборка открытого API MaxBotStat. --- # Открытый API Открытый API MaxBotStat позволяет читать аналитику и отправлять сообщения от имени бота из вашего кода. Его используют: * интеграция с CRM (передача новых контактов и диалогов); * информационные панели (выгрузка статистики); * автоматические рассылки и ответы; * регулярная выгрузка данных. ## Базовый адрес ``` https://app.maxbotstat.ru/api/v1 ``` Все методы возвращают `application/json`. ## Авторизация Используется **ключ API** в заголовке `X-API-Key`. Альтернатива — `Authorization: Bearer`: ``` X-API-Key: mbs_AbCd...EfGh # или Authorization: Bearer mbs_AbCd...EfGh ``` Подробнее: [Авторизация](/api/authentication). ## Разрешения Каждый ключ имеет одно или оба разрешения: | Разрешение | Что разрешено | | --- | --- | | `read` | чтение списков, контактов, сообщений, статистики | | `write` | отправка сообщений и рассылок | Все методы `GET` требуют `read`. `POST /broadcast` и `POST /send` требуют `write`. ## Методы | Метод | Путь | Описание | | --- | --- | --- | | `GET` | `/me` | Профиль владельца ключа и активные разрешения | | `GET` | `/bots` | Список всех ваших ботов | | `GET` | `/bots/{id}` | Карточка бота | | `GET` | `/bots/{id}/contacts` | Контакты бота (с постраничной выборкой) | | `GET` | `/bots/{id}/contacts/{userId}` | Карточка контакта | | `GET` | `/bots/{id}/messages` | История сообщений (фильтры по дате и пользователю) | | `GET` | `/bots/{id}/dialogs` | Лента диалогов (как в кабинете) | | `GET` | `/bots/{id}/stats` | Сводная статистика бота | | `GET` | `/bots/{id}/stats/timeline` | Подневная динамика (входящие/исходящие/новые контакты) | | `GET` | `/bots/{id}/sources` | Источники по UTM с числом контактов | | `GET` | `/bots/{id}/intents` | Список намерений с метриками | | `POST` | `/bots/{id}/send` | Отправить сообщение пользователю | | `POST` | `/bots/{id}/broadcast` | Запустить рассылку | ## Идентификаторы Везде используется **публичный идентификатор бота** (UUID), например `5d4e3a2b-...`. Внутренние числовые номера через API не отдаются. В заголовке HTTP подойдёт и числовой идентификатор (для обратной совместимости), но открытые интеграции должны использовать UUID. ## Формат ответов ### Списки ```json { "data": [ ... ], "total": 412, "limit": 100, "offset": 0 } ``` ### Один объект ```json { "id": "uuid", "name": "...", ... } ``` ### Ошибки ```json { "message": "Описание ошибки" } ``` Код HTTP: `4xx` — ошибки клиента, `5xx` — ошибки сервера. См. [Коды ошибок](/api/errors). ## Постраничная выборка Все списочные методы принимают: * `limit` — размер страницы. По умолчанию 100, не больше 1000. * `offset` — смещение. По умолчанию 0. Поле `total` в ответе — общее число элементов на сервере (не зависит от `limit/offset`). ::: tip Производительность Для больших выборок используйте `limit=1000` и идите по страницам. Постраничной выборки по курсору пока нет. ::: ## Лимиты запросов В текущем выпуске лимиты не строгие: * около 60 запросов в минуту на ключ (мягкое ограничение через nginx); * 100 одновременных открытых соединений на сервер. Если упираетесь — пишите в поддержку, расширим квоту. ## Версии Текущая версия — `v1`, она стабильна. При появлении несовместимых изменений мы: 1. выпустим `v2` параллельно; 2. оставим `v1` минимум на 6 месяцев; 3. предупредим всех, у кого время последнего использования ключа попадает в методы `v1`. ## Быстрый пример ```bash # 1. выпустите ключ в кабинете (Настройки → API) # 2. сохраните в переменную export MBS_KEY="mbs_..." # 3. получите список своих ботов curl "https://app.maxbotstat.ru/api/v1/bots" \ -H "X-API-Key: $MBS_KEY" # 4. возьмите идентификатор первого бота и попросите его статистику curl "https://app.maxbotstat.ru/api/v1/bots//stats" \ -H "X-API-Key: $MBS_KEY" ``` --- --- url: 'https://docs.maxbotstat.ru/api/authentication.md' description: >- Выпуск ключей API в кабинете MaxBotStat, разрешения «чтение» и «запись», отзыв ключа, передача в заголовке X-API-Key или Authorization Bearer. --- # Авторизация Открытый API авторизуется по **ключу API** — статической строкой, начинающейся с префикса `mbs_`. ``` mbs_AbCdEf...XyZ123 ``` Ключ показывается **один раз** при выпуске. Дальше в кабинете виден только префикс (`mbs_AbCdEf...`). ## Выпуск ключа 1. **Настройки → API → Создать ключ**. 2. Укажите имя (например, `crm-export`) — для вас, чтобы помнить, где он живёт. 3. Выберите разрешения: * `read` — только чтение (статистика, контакты, сообщения); * `write` — отправка (рассылки, одиночные сообщения); * оба — для интеграций с двусторонним обменом. 4. По желанию — `expires_at`. После этой даты ключ перестанет работать. 5. **Создать.** Скопируйте ключ. После закрытия окна восстановить его нельзя — выпустите новый. ## Использование Ключ передаётся в одном из двух заголовков: ```http X-API-Key: mbs_AbCdEf... ``` или ```http Authorization: Bearer mbs_AbCdEf... ``` Поведение одинаковое. ## Примеры ::: code-group ```bash [cURL] curl "https://app.maxbotstat.ru/api/v1/me" \ -H "X-API-Key: $MBS_KEY" ``` ```js [Node.js] const r = await fetch('https://app.maxbotstat.ru/api/v1/me', { headers: { 'X-API-Key': process.env.MBS_KEY }, }) console.log(await r.json()) ``` ```python [Python] import os, requests r = requests.get( 'https://app.maxbotstat.ru/api/v1/me', headers={'X-API-Key': os.environ['MBS_KEY']}, timeout=10, ) print(r.json()) ``` ```go [Go] req, _ := http.NewRequest("GET", "https://app.maxbotstat.ru/api/v1/me", nil) req.Header.Set("X-API-Key", os.Getenv("MBS_KEY")) resp, err := http.DefaultClient.Do(req) ``` ::: ## Проверить владельца ключа ```bash curl "https://app.maxbotstat.ru/api/v1/me" \ -H "X-API-Key: $MBS_KEY" ``` ```json { "id": "8a34...", "email": "user@example.com", "role": "user", "plan_key": "pro", "plan_until": "2026-06-01T00:00:00Z", "created_at": "2025-09-12T08:21:00Z", "scopes": ["read", "write"] } ``` ## Отзыв ключа В кабинете: **Настройки → API → Отозвать**. После отзыва любой запрос с этим ключом получит `401 API-ключ отозван`. ## Лимиты * До **20 активных ключей** на пользователя. После лимита нужно отозвать старые. * Срок действия — до 5 лет. * Префикс `mbs_` фиксирован, остальная часть — base64url (32 байта), около 43 знаков. ## Безопасность * Не публикуйте ключ в репозитории. Используйте `.env`, секреты сборочного конвейера или менеджер вроде [Vault](https://www.vaultproject.io/). * Если ключ утёк — отзовите его и выпустите новый. Все запросы со старым ключом мгновенно перестанут работать. * Ключи с разрешением `write` могут отправлять сообщения от имени бота — относитесь к ним как к токену бота. ## Когда использовать сессионный ключ кабинета Ваш кабинет использует **сессионный ключ**, выдаваемый при логине, со сроком 7 дней. Он работает на закрытых методах `/api/...` (без `v1`). Открытый API `/api/v1/...` — **только** на ключах API. Сессионный ключ туда не подходит. ## Коды ответа авторизации | Код | Сообщение | Что делать | | --- | --- | --- | | `401` | API-ключ обязателен | заголовок не пришёл | | `401` | Неверный API-ключ | опечатка или ключ удалён | | `401` | API-ключ отозван | выпустите новый | | `401` | Срок действия API-ключа истёк | продлите или выпустите новый | | `403` | Недостаточно прав: требуется scope "write" | выпустите ключ с нужным разрешением | --- --- url: 'https://docs.maxbotstat.ru/api/bots.md' description: >- Методы GET /bots и GET /bots/{id} в MaxBotStat — формат полей, примеры запросов и ответов. --- # Открытый API → Боты ## `GET /api/v1/bots` Список всех ботов, принадлежащих владельцу ключа. **Разрешение:** `read` ```bash curl "https://app.maxbotstat.ru/api/v1/bots" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "data": [ { "id": "5d4e3a2b-7c6f-4b8e-9d1a-2c3b4e5f6a7b", "name": "MyShop bot", "provider": "telegram", "active": true, "created_at": "2025-09-15T10:00:00Z", "last_proxy_at": "2026-04-30T15:23:01Z", "bot_display_name": "MyShop bot", "contacts_count": 412, "messages_24h": 87 } ] } ``` ### Поля | Поле | Тип | Описание | | --- | --- | --- | | `id` | строка (UUID) | публичный идентификатор бота | | `name` | строка | имя, заданное в кабинете | | `provider` | `telegram` или `max` | платформа бота | | `active` | булево | активен ли бот (если выключен — зеркало возвращает ошибку) | | `created_at` | ISO 8601 | когда привязан | | `last_proxy_at` | ISO 8601 или `null` | время последнего запроса через зеркало | | `bot_display_name` | строка | отображаемое имя бота из Telegram/Max | | `contacts_count` | целое | общее число контактов | | `messages_24h` | целое | сообщений за последние 24 часа | ## `GET /api/v1/bots/{id}` Расширенная карточка бота. `id` — публичный идентификатор. ```bash curl "https://app.maxbotstat.ru/api/v1/bots/5d4e3a2b-7c6f-4b8e-9d1a-2c3b4e5f6a7b" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "id": "5d4e3a2b-7c6f-4b8e-9d1a-2c3b4e5f6a7b", "name": "MyShop bot", "provider": "telegram", "active": true, "created_at": "2025-09-15T10:00:00Z", "last_proxy_at": "2026-04-30T15:23:01Z", "bot_display_name": "MyShop bot", "bot_avatar_url": "https://api.telegram.org/file/bot.../photo.jpg", "poll_offset": 0, "poll_last_at": null, "poll_last_error": null, "contacts_count": 412 } ``` ::: warning Без токена бота Поле `bot_token` через открытый API **никогда не возвращается** — даже владельцу. Если нужно увидеть токен, посмотрите его в кабинете один раз при привязке. ::: ## Ошибки | Код | Когда | | --- | --- | | `404` | бот с таким идентификатором не существует или принадлежит другому пользователю | | `401` | см. [Авторизацию](/api/authentication) | ## Что нельзя через открытый API * **Привязать бота** — только через кабинет (требует подтверждения почты и проверки токена). * **Удалить бота** — только через кабинет. Эти операции требуют дополнительного взаимодействия и проверок, поэтому в открытом API их нет. Если нужна автоматизация — пишите в поддержку. --- --- url: 'https://docs.maxbotstat.ru/api/contacts.md' description: >- Методы для списка контактов и карточки контакта в MaxBotStat — постраничная выборка, метаданные, источник. --- # Открытый API → Контакты ## `GET /api/v1/bots/{id}/contacts` Список контактов бота с постраничной выборкой. **Разрешение:** `read` ### Параметры | Параметр | Тип | По умолчанию | Описание | | --- | --- | --- | --- | | `limit` | целое | 100 | размер страницы (1–1000) | | `offset` | целое | 0 | смещение | ### Запрос ```bash curl "https://app.maxbotstat.ru/api/v1/bots//contacts?limit=50&offset=0" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "data": [ { "id": "9f2e...", "external_user_id": "123456789", "username": "anna", "first_name": "Анна", "last_name": "Петрова", "is_premium": false, "last_seen_at": "2026-04-30T15:23:01Z", "messages_count": 42 } ], "total": 412, "limit": 50, "offset": 0 } ``` Контакты отсортированы по `last_seen_at` по убыванию — последние активные сверху. ## `GET /api/v1/bots/{id}/contacts/{userId}` Карточка одного контакта. `userId` — это `external_user_id` (идентификатор пользователя в Telegram/Max). ```bash curl "https://app.maxbotstat.ru/api/v1/bots//contacts/123456789" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "contact": { "id": "9f2e...", "external_user_id": "123456789", "username": "anna", "first_name": "Анна", "last_name": "Петрова", "is_premium": false, "phone": null, "last_seen_at": "2026-04-30T15:23:01Z" }, "stats": { "total_messages": 42, "inbound": 31, "outbound": 11, "first_at": "2025-09-20T08:00:00Z", "last_at": "2026-04-30T15:23:01Z" }, "attribution": { "source_value": "instagram", "campaign_name": "spring", "first_seen_at": "2025-09-20T08:00:00Z", "last_seen_at": "2025-09-20T08:00:00Z", "touches": 1 } } ``` | Объект | Описание | | --- | --- | | `contact` | метаданные пользователя | | `stats` | сводная статистика по переписке | | `attribution` | источник трафика (UTM); `null`, если контакт пришёл вне UTM | ## Поиск контактов Поиск по подстроке через открытый API пока недоступен. Альтернатива: 1. Скачайте все контакты страницами; 2. Фильтруйте на своей стороне. Для большой базы это может быть тяжело — следите за обновлениями API. Поиск планируется в `v1.1`. ## Связь с сообщениями `external_user_id` — связующий ключ между контактами, сообщениями и источниками. Используйте его в: * `GET /api/v1/bots/{id}/messages?userId=` * `POST /api/v1/bots/{id}/send` (поле `userId`) ## Ошибки | Код | Сообщение | Когда | | --- | --- | --- | | `404` | `Bot not found` | бот не принадлежит вам | | `404` | `Contact not found` | контакта с таким `external_user_id` бот не видел | | `400` | неверный `limit/offset` | вне диапазона | --- --- url: 'https://docs.maxbotstat.ru/api/messages.md' description: >- Методы для истории сообщений и диалогов в MaxBotStat — фильтры по дате, пользователю, формат полей. --- # Открытый API → Сообщения и диалоги ## `GET /api/v1/bots/{id}/messages` История сообщений бота. По умолчанию — последние 100 во всех диалогах. **Разрешение:** `read` ### Параметры | Параметр | Тип | По умолчанию | Описание | | --- | --- | --- | --- | | `limit` | целое | 100 | 1–1000 | | `userId` | строка | — | фильтр по `external_user_id` | | `from` | ISO 8601 / дата | — | сообщения не раньше | | `to` | ISO 8601 / дата | — | сообщения не позже | ### Примеры ```bash # последние 100 сообщений curl "https://app.maxbotstat.ru/api/v1/bots//messages" \ -H "X-API-Key: $MBS_KEY" # переписка с конкретным пользователем curl "https://app.maxbotstat.ru/api/v1/bots//messages?userId=123456789&limit=500" \ -H "X-API-Key: $MBS_KEY" # за прошлый месяц curl "https://app.maxbotstat.ru/api/v1/bots//messages?from=2026-04-01&to=2026-04-30&limit=1000" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "data": [ { "id": "5d31...", "direction": "in", "external_user_id": "123456789", "text": "/start utm_source=instagram", "created_at": "2026-04-30T15:23:01Z" }, { "id": "a4b2...", "direction": "out", "external_user_id": "123456789", "text": "Здравствуйте! Чем помочь?", "created_at": "2026-04-30T15:23:05Z" } ], "limit": 100 } ``` Сортировка — `created_at` по убыванию (новые сверху). ::: info Без исходного обновления Поле `raw_json` (исходное обновление Telegram/Max) через открытый API не отдаётся для экономии трафика. Если нужно — оно доступно команде поддержки в режиме отладки. ::: ## `GET /api/v1/bots/{id}/dialogs` Список диалогов в порядке последнего сообщения. Удобно для отображения списка переписок в собственном кабинете. ```bash curl "https://app.maxbotstat.ru/api/v1/bots//dialogs?limit=50" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "data": [ { "id": "9f2e...", "external_user_id": "123456789", "username": "anna", "first_name": "Анна", "last_name": "Петрова", "last_text": "Спасибо!", "last_direction": "in", "last_at": "2026-04-30T15:23:01Z", "messages_total": 42 } ], "limit": 50 } ``` | Поле | Описание | | --- | --- | | `last_text` | первые 200 знаков последнего сообщения | | `last_direction` | `in` (от пользователя) или `out` (от бота) | | `last_at` | время последнего сообщения | | `messages_total` | общее число сообщений в этом диалоге | ## Полнотекстовый поиск В открытом API поиска по тексту сообщений пока **нет**. Если нужно искать по тексту: 1. Загрузите сообщения в свою базу через периодическую выгрузку; 2. Используйте Postgres `tsvector`, ElasticSearch или Meilisearch. ## Ограничения * `limit` обрезается до 1000. * Запрос с `userId` для несуществующего контакта вернёт пустой `data` (не ошибка). * При очень большом периоде используйте постраничную выборку по диапазонам `created_at`, увеличивая `from` в каждом следующем запросе. --- --- url: 'https://docs.maxbotstat.ru/api/stats.md' description: >- Методы сводной статистики и таймлайна по дням в MaxBotStat — поля ответа, примеры использования для информационных панелей. --- # Открытый API → Статистика ## `GET /api/v1/bots/{id}/stats` Сводная статистика бота на текущий момент. **Разрешение:** `read` ```bash curl "https://app.maxbotstat.ru/api/v1/bots//stats" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "contacts_total": 412, "contacts_active_24h": 31, "messages_total": 8234, "messages_in": 4117, "messages_out": 4117, "messages_24h": 87, "new_users_7d": 18, "active_users_7d": 92 } ``` | Поле | Описание | | --- | --- | | `contacts_total` | всего контактов в базе | | `contacts_active_24h` | у скольких есть `last_seen_at` ≤ 24 часов назад | | `messages_total` | всего сообщений в обе стороны | | `messages_in` | входящих от пользователей | | `messages_out` | исходящих от бота (через зеркало и API) | | `messages_24h` | сообщений (входящих и исходящих) за последние 24 часа | | `new_users_7d` | контактов, у которых **первое** сообщение в последние 7 дней | | `active_users_7d` | контактов, активных в последние 7 дней, но первый раз писали раньше | ## `GET /api/v1/bots/{id}/stats/timeline` Подневная динамика — сообщения и новые контакты. ### Параметры | Параметр | Тип | По умолчанию | Описание | | --- | --- | --- | --- | | `days` | целое | 30 | 1–365 | ### Запрос ```bash curl "https://app.maxbotstat.ru/api/v1/bots//stats/timeline?days=30" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "data": [ { "date": "2026-04-01", "messages_in": 45, "messages_out": 50, "new_contacts": 3 }, { "date": "2026-04-02", "messages_in": 67, "messages_out": 72, "new_contacts": 5 }, { "date": "2026-04-03", "messages_in": 23, "messages_out": 25, "new_contacts": 1 } ], "days": 30 } ``` Каждый элемент `data` — один день. Дни с нулём активности тоже включены (`0/0/0`), чтобы график не «прыгал». ## Использование в информационной панели Пример: построить график «новые контакты за месяц» прямо в браузере. ```html ``` ::: warning Не показывайте ключ в браузере В этом примере ключ виден в браузере — это **только** для образца. В рабочем варианте ходите за статистикой со своего сервера, а ключ держите в секретах. ::: ## Кеш Метод `stats` возвращает свежие данные без кеширования. Для тяжёлых интеграций (BigQuery, ClickHouse, BI) делайте выгрузку раз в час и кешируйте результат у себя. ## Пример: панель по нескольким ботам ```js const bots = await fetch('https://app.maxbotstat.ru/api/v1/bots', { headers: { 'X-API-Key': process.env.MBS_KEY }, }).then(r => r.json()) const stats = await Promise.all( bots.data.map(b => fetch(`https://app.maxbotstat.ru/api/v1/bots/${b.id}/stats`, { headers: { 'X-API-Key': process.env.MBS_KEY }, }).then(r => r.json()).then(s => ({ name: b.name, ...s })) ) ) console.table(stats) ``` --- --- url: 'https://docs.maxbotstat.ru/api/sources-intents.md' description: >- Методы для источников по UTM и категорий сообщений (намерений) в MaxBotStat — формат ответа и примеры запросов. --- # Открытый API → Источники и намерения ## `GET /api/v1/bots/{id}/sources` Сводка по источникам трафика (UTM). **Разрешение:** `read` ```bash curl "https://app.maxbotstat.ru/api/v1/bots//sources" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "utm_key": "utm_source", "data": [ { "source_value": "instagram", "campaign_name": "spring", "contacts_count": 412, "touches": 1024 }, { "source_value": "ads", "campaign_name": null, "contacts_count": 88, "touches": 162 }, { "source_value": "— unmapped","campaign_name": null, "contacts_count": 5, "touches": 12 } ] } ``` * `utm_key` — текущий ключ UTM, заданный в настройках бота. * `source_value: "— unmapped"` — контакты без `/start`-параметра. * `touches` — суммарное число касаний (повторные заходы по одной и той же ссылке). См. также: [Руководство → Источники по UTM](/guide/sources). ## `GET /api/v1/bots/{id}/intents` Список намерений с метриками. **Разрешение:** `read` ```bash curl "https://app.maxbotstat.ru/api/v1/bots//intents" \ -H "X-API-Key: $MBS_KEY" ``` ### Ответ ```json { "data": [ { "id": "67d4...", "name": "payment", "description": "Вопросы про оплату", "color": "#16a34a", "is_active": true, "users_count": 312, "messages_count": 845, "created_at": "2025-09-01T10:00:00Z" }, { "id": "8b1f...", "name": "complaint", "description": "Жалобы и недовольство", "color": "#dc2626", "is_active": true, "users_count": 28, "messages_count": 67, "created_at": "2025-09-15T14:00:00Z" } ] } ``` | Поле | Описание | | --- | --- | | `id` | публичный идентификатор намерения | | `name` | технический ключ | | `description` | человеко-читаемое описание | | `color` | цвет для подсветки в кабинете (16-ричный) | | `is_active` | если `false`, намерение не применяется к новым сообщениям | | `users_count` | контактов, у которых хоть раз сработало намерение | | `messages_count` | сообщений, попавших в намерение | ## Что нельзя через открытый API * **Создать или изменить намерение.** Это делается через закрытый API кабинета (`POST /api/bots/:id/intents`), который требует сессионного ключа. * **Получить список сообщений конкретного намерения.** Используйте кабинет или закрытый API. Если нужны эти возможности через открытый API — пишите в поддержку, добавим в `v1.1`. ## Связь с воронками Намерения — отличный материал для условий этапов воронки. См. [Руководство → Воронки](/guide/funnel). --- --- url: 'https://docs.maxbotstat.ru/api/send.md' description: >- Метод POST /bots/{id}/send для отправки одиночного сообщения через MaxBotStat — параметры, ошибки, примеры. --- # Открытый API → Отправка сообщений ## `POST /api/v1/bots/{id}/send` Отправляет текстовое сообщение конкретному пользователю от имени вашего бота. **Разрешение:** `write` ### Тело запроса ```json { "userId": "123456789", "text": "Здравствуйте! Чем помочь?" } ``` | Поле | Тип | Обязательно | Описание | | --- | --- | --- | --- | | `userId` | строка | да | `external_user_id` контакта (идентификатор Telegram/Max) | | `text` | строка | да | до 4000 знаков | ### Запрос ```bash curl -X POST "https://app.maxbotstat.ru/api/v1/bots//send" \ -H "X-API-Key: $MBS_KEY" \ -H "Content-Type: application/json" \ -d '{"userId":"123456789","text":"Здравствуйте! Чем помочь?"}' ``` ### Ответ ```json { "ok": true, "id": "5d31a4b2-...", "direction": "out", "text": "Здравствуйте! Чем помочь?", "created_at": "2026-04-30T15:23:01Z", "provider": { "ok": true, "result": { "message_id": 8901 } } } ``` * `id` — публичный идентификатор сообщения в MaxBotStat (не путать с `message_id` Telegram). * `provider` — необработанный ответ от Telegram/Max API. У Telegram там `result.message_id` — это идентификатор сообщения внутри Telegram. ## Что происходит под капотом Для Telegram: ``` POST https://api.telegram.org/bot/sendMessage Content-Type: application/json { "chat_id": "", "text": "" } ``` Для Max: ``` POST https://platform-api.max.ru/messages?chat_id= Authorization: Content-Type: application/json { "text": "" } ``` После успешной отправки запись добавляется в `messages` с `direction='out'` и срабатывает событие `message.outbound` (если у вас есть подписки). ## Ошибки | Код | Сообщение | Что значит | | --- | --- | --- | | `400` | `userId and text required` | пропущено одно из обязательных полей | | `400` | `Personal send requires bot token` | у бота не указан токен — отправка невозможна | | `403` | `Недостаточно прав: требуется scope "write"` | ключ выпущен только с `read` | | `404` | `Bot not found` | бот не принадлежит вам | | `502` | `Provider send failed` | Telegram/Max ответил ошибкой; в `provider` — детали | Пример `502`: ```json { "message": "Provider send failed", "provider": { "ok": false, "error_code": 403, "description": "Forbidden: bot was blocked by the user" } } ``` ## Примеры ::: code-group ```js [Node.js] const r = await fetch(`https://app.maxbotstat.ru/api/v1/bots/${botId}/send`, { method: 'POST', headers: { 'X-API-Key': process.env.MBS_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ userId: '123456', text: 'Привет!' }), }) const data = await r.json() if (!r.ok) throw new Error(data.message) ``` ```python [Python] import requests, os r = requests.post( f'https://app.maxbotstat.ru/api/v1/bots/{bot_id}/send', headers={'X-API-Key': os.environ['MBS_KEY']}, json={'userId': '123456', 'text': 'Привет!'}, timeout=15, ) r.raise_for_status() print(r.json()) ``` ```php [PHP] $ch = curl_init("https://app.maxbotstat.ru/api/v1/bots/{$botId}/send"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => ["X-API-Key: {$_ENV['MBS_KEY']}", "Content-Type: application/json"], CURLOPT_POSTFIELDS => json_encode(["userId" => "123456", "text" => "Привет!"]), CURLOPT_RETURNTRANSFER => true, ]); $resp = curl_exec($ch); ``` ::: ## Ограничения * Только текст. Для медиа используйте кабинет или `/broadcast` с файлом. * Telegram запрещает ботам начинать диалог с незнакомым пользователем — `userId` должен быть из контактов бота. * Лимиты Telegram: 30 сообщений в секунду, 1 в секунду в одном диалоге. MaxBotStat не разгоняет — повторы делайте сами по `429`. ## Защита от повтора Если при `502` вы повторяете запрос — Telegram, возможно, уже доставил сообщение, и пользователь увидит дубль. Защититесь: * сохраняйте идентификатор сообщения после первого успеха; * при повторе проверяйте через `GET /api/v1/bots/{id}/messages?userId=...` — есть ли уже исходящее сообщение с нужным текстом за последние 30 секунд. --- --- url: 'https://docs.maxbotstat.ru/api/broadcast.md' description: >- Метод POST /bots/{id}/broadcast для запуска рассылки в Telegram/Max через MaxBotStat — поведение, лимиты, формат ответа. --- # Открытый API → Рассылка ## `POST /api/v1/bots/{id}/broadcast` Отправляет текстовое сообщение **всем контактам** бота. Запрос синхронный — возвращается, когда последний пользователь обработан. **Разрешение:** `write` ### Тело запроса ```json { "text": "Привет! Скидка 20% по промокоду SPRING до конца недели." } ``` | Поле | Тип | Описание | | --- | --- | --- | | `text` | строка | до 4000 знаков | ### Запрос ```bash curl -X POST "https://app.maxbotstat.ru/api/v1/bots//broadcast" \ -H "X-API-Key: $MBS_KEY" \ -H "Content-Type: application/json" \ -d '{"text":"Привет!"}' ``` ### Ответ ```json { "id": "8c3a...", "total_count": 412, "sent_count": 408, "failed_count": 4, "created_at": "2026-04-30T12:00:00Z" } ``` | Поле | Описание | | --- | --- | | `id` | публичный идентификатор рассылки в `broadcasts` | | `total_count` | сколько контактов было выбрано (= все контакты бота) | | `sent_count` | сколько успешно доставлено | | `failed_count` | сколько не доставлено (заблокировали бота, ошибка Telegram, недоступная сеть) | | `created_at` | время старта | ## Поведение * На каждого получателя — отдельный вызов Telegram `sendMessage` или Max `POST /messages`. * Отправляется последовательно (без распараллеливания), чтобы не получить `429` от Telegram. * При сбое к одному получателю остальные не пострадают — счётчик неудачных увеличивается, цикл продолжается. * В таблицу `messages` записывается каждое успешно отправленное сообщение (`direction='out'`). ## Сегментации в API нет `POST /broadcast` шлёт **всем** контактам бота. Для сегментов: * используйте кабинет (он поддерживает фильтры по UTM, намерениям, дате); * или сделайте свою сегментацию: получите список контактов через `/api/v1/bots/{id}/contacts`, отфильтруйте на своей стороне, шлите по одному через `/send`. ## Ошибки | Код | Сообщение | Что значит | | --- | --- | --- | | `400` | `text required` | пустое тело | | `400` | `text too long (max 4000 chars)` | текст длиннее лимита Telegram | | `400` | `Broadcast requires bot token` | бот привязан без токена — отправлять некому | | `403` | недостаточно прав | ключ без `write` | | `404` | `Bot not found` | бот не ваш или не существует | ## Тайм-аут Запрос **может выполняться долго** — на 5000 контактов это около 3 минут. Учитывайте это: * `curl --max-time 600`, чтобы не закрыло раньше; * в Node.js — `signal: AbortSignal.timeout(600_000)`; * в Python `requests` — `timeout=600`. Если ваш HTTP-клиент отвалится по тайм-ауту, рассылка **продолжит идти на сервере** — состояние можно посмотреть в кабинете в разделе **Рассылки**. ## Лимиты Telegram | Ограничение | Значение | | --- | --- | | Сообщений в секунду одному получателю | 1 | | Сообщений в секунду разным получателям | 30 | | Сообщений в минуту в одну группу | 20 | При превышении — `429 Too Many Requests` с заголовком `Retry-After`. MaxBotStat учитывает это и не разгоняет цикл искусственно. ## Защита от повтора Сервер **не делает автоматическое объединение** рассылок. Если вы дважды нажмёте `POST /broadcast` с одним и тем же текстом — пользователи получат **два** сообщения. Защититесь: * сохраняйте `id` ответа на стороне клиента; * не повторяйте запрос на ответ `5xx` — Telegram уже принял сообщения, повтор приведёт к дублям. ## Аналитика рассылки Идентификатор ответа можно использовать для отчёта через закрытый API кабинета (`/api/bots/:id/broadcasts`). В открытом API пока нет метода для просмотра прошлых рассылок — добавим в `v1.1`. --- --- url: 'https://docs.maxbotstat.ru/api/webhooks.md' description: >- Получайте события message.created, message.outbound, contact.created на свой адрес — формат тела, подпись HMAC-SHA256, тестовая доставка. --- # Подписка на события MaxBotStat шлёт уведомления о событиях на указанный вами HTTPS-адрес. Это удобно, когда: * у вас CRM, и нужно получать новых контактов в реальном времени; * хочется складывать сообщения в свою базу без постоянного опроса открытого API; * нужно уведомление в Slack или Telegram-чате при определённом событии. ## Поддерживаемые события | Событие | Когда срабатывает | | --- | --- | | `message.created` | новое **входящее** сообщение от пользователя | | `message.outbound` | бот отправил сообщение (через зеркало, кабинет или открытый API) | | `contact.created` | контакт впервые появился в базе | В будущем добавим `funnel.step_passed`, `intent.matched`, `broadcast.completed`. ## Создать подписку ::: warning Только через закрытый API кабинета Управление подписками сейчас делается через закрытый API (`/api/me/webhooks`) с сессионным ключом из кабинета. В открытом API этого метода пока нет — мы намеренно не даём управлять подписками через постоянные ключи. ::: Через кабинет: **Настройки → Подписки на события → Создать**. Через закрытый API: ```bash curl -X POST "https://app.maxbotstat.ru/api/me/webhooks" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "url": "https://yourapp.com/mbs-hook", "events": ["message.created", "message.outbound", "contact.created"], "bot_id": "5d4e3a2b-..." }' ``` Ответ: ```json { "id": "67c8...", "url": "https://yourapp.com/mbs-hook", "events": ["message.created", "message.outbound", "contact.created"], "active": true, "created_at": "2026-04-30T12:00:00Z", "secret": "whsec_AbCd...XyZ" } ``` ::: danger Сохраните `secret` `secret` отдаётся **только при создании**. Дальше через API его не получить. Он нужен для проверки подписи входящих уведомлений. ::: `bot_id` необязателен. Если указан — события приходят только от этого бота. Если не указан — со всех ваших ботов. ## Формат входящего запроса MaxBotStat шлёт `POST` на ваш адрес: ```http POST /mbs-hook HTTP/1.1 Host: yourapp.com Content-Type: application/json User-Agent: MaxBotStat-Webhook/1 X-Webhook-Event: message.created X-Webhook-Signature: sha256= { "event": "message.created", "delivered_at": "2026-04-30T15:23:01.123Z", "subscription_id": "67c8...", "data": { "bot_id": "5d4e3a2b-...", "message_id": "5d31...", "direction": "in", "external_user_id": "123456789", "text": "Привет", "created_at": "2026-04-30T15:23:01Z" } } ``` ## Проверка подписи Подпись считается так: ``` HMAC-SHA256(secret, raw_body) → hex → "sha256=" + hex ``` ::: code-group ```js [Node.js] import crypto from 'crypto' function verifyWebhook(rawBody, signature, secret) { const expected = 'sha256=' + crypto.createHmac('sha256', secret) .update(rawBody) .digest('hex') return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)) } // Express app.post('/mbs-hook', express.raw({ type: 'application/json' }), (req, res) => { if (!verifyWebhook(req.body, req.headers['x-webhook-signature'], process.env.MBS_SECRET)) { return res.status(401).end() } const event = JSON.parse(req.body.toString()) // обработка... res.json({ ok: true }) }) ``` ```python [Python] import hmac, hashlib def verify_webhook(raw_body: bytes, signature: str, secret: str) -> bool: expected = 'sha256=' + hmac.new( secret.encode(), raw_body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature) ``` ```go [Go] func verifyWebhook(rawBody []byte, signature, secret string) bool { mac := hmac.New(sha256.New, []byte(secret)) mac.Write(rawBody) expected := "sha256=" + hex.EncodeToString(mac.Sum(nil)) return hmac.Equal([]byte(expected), []byte(signature)) } ``` ::: ## Тестовая доставка В кабинете — кнопка **Тест**. Она шлёт событие `test.ping`: ```json { "event": "test.ping", "delivered_at": "...", "subscription_id": "...", "data": { "message": "Тестовая доставка от MaxBotStat", "timestamp": "..." } } ``` Через закрытый API: ```bash curl -X POST "https://app.maxbotstat.ru/api/me/webhooks//test" \ -H "Authorization: Bearer " ``` ## Повторы и тайм-аут * Тайм-аут на ваш ответ — **10 секунд**. * Если ответ **не 2xx** — MaxBotStat **не повторяет**. История неудач видна через `/api/me/webhooks//deliveries`. * Журнал доставок хранит 50 последних запросов на подписку. ::: tip Делайте обработку асинхронной Не делайте тяжёлые операции в обработчике уведомления. Положите событие в очередь (Redis, SQS, Kafka) и быстро ответьте `200`. ::: ## Просмотр истории доставок ```bash curl "https://app.maxbotstat.ru/api/me/webhooks//deliveries" \ -H "Authorization: Bearer " ``` ```json [ { "event": "message.created", "status_code": 200, "error": null, "duration_ms": 87, "created_at": "..." }, { "event": "message.created", "status_code": 502, "error": "fetch failed", "duration_ms": 30, "created_at": "..." } ] ``` ## Лимиты * Максимум **20 подписок** на пользователя. * Размер `events` — любые из поддерживаемых, **минимум одно**. * Адрес — только `http://` или `https://`, до 500 знаков. --- --- url: 'https://docs.maxbotstat.ru/api/errors.md' description: >- Список кодов HTTP и сообщений об ошибках MaxBotStat — что значит каждый, как обработать в клиенте. --- # Коды ошибок открытого API Все ошибки открытого API возвращают тело вида: ```json { "message": "Описание ошибки" } ``` Код HTTP указывает класс ошибки. ## 4xx — ошибки клиента | Код | Сообщение | Причина | Что делать | | --- | --- | --- | --- | | `400` | `text required` | пустое поле в теле | проверить тело | | `400` | `text too long (max 4000 chars)` | превышен лимит Telegram | сократить текст или разбить на несколько | | `400` | `userId and text required` | `/send` без userId/text | заполнить оба поля | | `400` | `Personal send requires bot token` | у бота не задан токен | добавить токен в кабинете | | `400` | `Broadcast requires bot token` | то же для рассылки | — | | `400` | `kind must be photo, audio or file` | неверный `kind` в `multipart` | использовать одно из трёх значений | | `400` | `platform must be all, tg or max` | неверная платформа в `/broadcast` закрытого API | — | | `401` | `API-ключ обязателен` | заголовок не пришёл | добавить `X-API-Key` | | `401` | `Неверный API-ключ` | опечатка или удалён | проверить ключ | | `401` | `API-ключ отозван` | вы или администратор его отозвали | выпустить новый | | `401` | `Срок действия API-ключа истёк` | `expires_at` в прошлом | продлить или выпустить новый | | `401` | `Требуется авторизация` (закрытый API) | нет сессии | войти в кабинет повторно | | `401` | `Сессия истекла, войдите заново` | сессия просрочена (7 дней) | повторный вход | | `403` | `Недостаточно прав: требуется scope "read"` | нужен ключ с `read` | выпустить новый ключ | | `403` | `Недостаточно прав: требуется scope "write"` | нужен ключ с `write` | — | | `403` | `Admins cannot create bots` | команда поддержки не может иметь своих ботов | войти под пользовательской учёткой | | `404` | `Bot not found` | бот не существует или принадлежит другому | проверить идентификатор | | `404` | `Contact not found` | контакта с таким `external_user_id` нет | — | | `404` | `Подписка не найдена` | подписка на события | — | | `409` | `Пользователь с таким email уже существует` | при регистрации | — | | `409` | `Бот с таким ID/token уже добавлен` | для одной платформы токен уникален | удалите старого | | `429` | `Достигнут лимит активных ключей (20)` | ключей API | отозвать старые | | `429` | `Достигнут лимит подписок (20)` | подписок на события | удалить ненужные | ## 5xx — ошибки сервера | Код | Сообщение | Причина | Что делать | | --- | --- | --- | --- | | `500` | `Ошибка авторизации` | внутренняя ошибка базы при проверке ключа | повторить через 5 секунд | | `500` | без `message` | необработанное исключение | повторить, при повторе — в поддержку | | `502` | `Provider send failed` | Telegram/Max ответил не-2xx | см. `provider` в теле для деталей | | `502` | `tg ` или `max ` | сетевая ошибка к платформе | повторить | Пример `502` от Telegram: ```json { "message": "Provider send failed", "provider": { "ok": false, "error_code": 403, "description": "Forbidden: bot was blocked by the user" } } ``` ## Стандартные ошибки Telegram (в `provider`) | `error_code` | Что значит | | --- | --- | | `400` | Bad Request — неверный `chat_id`, текст со сломанной разметкой | | `403` | Forbidden — бот заблокирован пользователем или удалён из чата | | `404` | Not Found — `chat_id` не существует | | `429` | Too Many Requests — превышен лимит, ждать `Retry-After` секунд | ## Повторы | Класс ошибок | Стоит ли повторять | | --- | --- | | `4xx` (кроме `429`) | **нет** — ошибка клиента, исправляйте тело запроса | | `429` | да, с задержкой `Retry-After` | | `502`, `503`, `504` | да, с увеличивающейся задержкой (1 с, 2 с, 4 с, 8 с) | | `500` | можно один раз, без зацикливания | ## Метод проверки доступности ```bash curl "https://app.maxbotstat.ru/health" ``` ```json { "ok": true } ``` Используйте для проверки доступности API в системе наблюдения. --- --- url: 'https://docs.maxbotstat.ru/faq.md' description: >- Короткие ответы на частые вопросы про MaxBotStat — замена адреса API, аналитика бота, рассылки, открытый API, лимиты, безопасность. --- # Частые вопросы ## Общие ### Что делает MaxBotStat? Аналитика и автоматизация для Telegram- и Max-ботов через прозрачное зеркало API. Подробно — [Что такое MaxBotStat](/guide/getting-started). ### Сколько стоит начать? MaxBotStat работает на нашем сервере. Бесплатный тариф позволяет привязать одного бота с лимитом сообщений; для большего — платные тарифы. ## Подключение ### Какие платформы поддерживаются? [Telegram](https://core.telegram.org/bots) и [Max](https://max.ru). Подключение разное по форме токена, но логика зеркала одинаковая. ### Что делать, чтобы подключить бота? Привязать бота в кабинете и поменять в коде бота базовый адрес API: * Telegram: `https://api.telegram.org` → `https://api-tg.app.maxbotstat.ru` * Max: `https://platform-api.max.ru` → `https://api-max.app.maxbotstat.ru` Все методы (`getMe`, `sendMessage`, `getUpdates`, `setWebhook`) остаются прежними. Полные примеры на популярных библиотеках — в разделе [Замена адреса API в коде бота](/guide/connect). ### Бот без токена — что теряется? * Не работают рассылки и одиночные сообщения от имени бота из кабинета. * Не загружаются изображения профиля контактов автоматически. * `POST /api/v1/.../send` и `POST /api/v1/.../broadcast` возвращают `400 Personal send requires bot token`. ### Можно ли использовать MaxBotStat и свою аналитику одновременно? Да. Замена адреса API ничего не ломает в логике вашего бота — он по-прежнему сам обрабатывает входящие сообщения и сам собирает свою статистику. MaxBotStat работает параллельно. ### Как откатиться? Верните в коде старый адрес `https://api.telegram.org`. Аналитика перестанет собираться, бот в кабинете останется. Когда понадобится — измените адрес обратно. ## Аналитика ### Какие данные сохраняются? * Контакт (идентификатор, `username`, имя, признак Telegram Premium, телефон если поделился, время последнего сообщения). * Сообщения (текст, направление, время). * Источник `/start` (UTM). * Исходное обновление (`raw_json`). Команде доступны также изображения и медиа, отправленные через бот. ### Что с GDPR и 152-ФЗ? Платформа хранит персональные данные пользователей бота (идентификатор, имя, иногда телефон). По 152-ФЗ оператор данных — **владелец бота** (вы). MaxBotStat — обработчик. При удалении бота данные становятся недоступны через кабинет и открытый API; полное удаление по запросу пользователя — через поддержку. ### Сколько данных хранится по умолчанию? В текущем выпуске — без срока. Сообщения и контакты живут, пока вы не удалите бота или не попросите чистку явно. ### Можно ли выгрузить данные? Да, через открытый API: контакты, сообщения, статистика. Подробнее — [Открытый API](/api/overview). ## Рассылки ### Как быстро отправляется рассылка? Telegram ограничивает 30 сообщений в секунду. На 5000 контактов это около 3 минут. MaxBotStat не разгоняет искусственно, чтобы не получить блокировку Telegram. ### Можно ли запланировать рассылку? В текущем выпуске — нет. Запланированные рассылки в плане. ### Можно ли отменить запущенную рассылку? В кабинете — нет. Через закрытый API кабинета — есть кнопка остановки. Отправленные до этого момента сообщения остаются в базе. ### Что если бот заблокирован пользователем? Рассылка увеличит счётчик недоставленных. Контакт остаётся в базе, но при следующих рассылках снова окажется среди недоставленных. ## Открытый API ### Чем `/api/...` отличается от `/api/v1/...`? `/api/...` — закрытый API кабинета, работает по сессионному ключу из логина (живёт 7 дней). `/api/v1/...` — открытый, работает по постоянному ключу (`mbs_...`). ### Можно ли использовать ключ API в браузере? Технически да, но **не рекомендуется**. Кто угодно увидит ключ в инструментах разработчика и сможет шлюзить рассылки от вашего имени. Делайте посредник на своём сервере. ### Какой лимит частоты запросов? В текущем выпуске — мягкий (около 60 запросов в минуту на ключ). Жёстких пределов нет, но злоупотребление будет ограничено индивидуально. ### Как тестировать API локально? Привяжите бота, замените адрес API в локальном коде на `https://api-tg.app.maxbotstat.ru`. Все запросы вашего бота попадут в нашу аналитику, а сам бот будет работать как раньше. ## Деньги ### Сколько стоит? Зависит от тарифа. Открытый список — `GET /api/plans`. Бесплатный тариф — один бот и ограниченный объём сообщений. ### Как оплатить? Через [Robokassa](https://robokassa.com): карта, СБП, электронные деньги. После ответного запроса от Robokassa план активируется автоматически в течение минуты. ### Возвраты? В индивидуальном порядке через поддержку. Стандартный срок рассмотрения — 14 дней. ### Можно ли работать командой? Да, на тарифе **Макс** в одном аккаунте могут работать **до 10 человек**: владелец и до девяти приглашённых. Подробнее — в разделе [Команда](./guide/team). ## Безопасность ### Где хранятся токены ботов? В Postgres, в зашифрованном виде на уровне приложения. Через открытый API не возвращаются никогда — даже владельцу. ### Что с TLS? `docs.maxbotstat.ru`, `app.maxbotstat.ru` и поддомены — Let's Encrypt, автообновление. TLS 1.2 и 1.3. ### Что делать, если ключ утёк? В кабинете: **Настройки → API → Отозвать**. После этого старый ключ возвращает `401`. Выпустите новый. ### Как проверить, кто и когда использовал ключ? В кабинете: **Настройки → API** — таблица показывает время последнего использования и адрес для каждого ключа. ## Разное ### Где живёт сервис? Тестовый стенд — `app.maxbotstat.ru`. Для рабочего использования выпустим отдельный домен с SLA. ### Можно ли получить счёт или договор? Для юрлиц — через поддержку, тема `Корпоративная подписка`. ### Где документация для языковых моделей? См. [`/llms.txt`](https://docs.maxbotstat.ru/llms.txt) и [`/llms-full.txt`](https://docs.maxbotstat.ru/llms-full.txt). Подробнее: [llmstxt.org](https://llmstxt.org/).