Документация API
REST API для интеграции MeerBot в ваш продукт. OpenAI-совместимый формат. Подходит для любого языка программирования.
Быстрый старт
Три шага, чтобы отправить первый запрос:
- 1Зарегистрируйтесь и создайте бота в личном кабинете
- 2Получите API-ключ в разделе «API-ключи»
- 3Отправьте запрос:
curl -X POST https://meerbot.ru/api/v1/chat \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"assistantId": 1,
"message": "Привет! Как вы работаете?"
}'Аутентификация
Все запросы к API требуют Bearer-токен в заголовке Authorization.
Authorization: Bearer YOUR_API_KEY
Chat
Отправка сообщений вашему ассистенту. Поддерживает сессии для многоходовых диалогов.
Отправить сообщение и получить ответ ассистента.
Тело запроса
| Поле | Тип | Описание |
|---|---|---|
| assistantId | number | ID ассистента. Обязательный. |
| message | string | Текст сообщения. Обязательный. |
| sessionId | string | ID сессии для продолжения диалога. Опциональный. |
curl -X POST https://meerbot.ru/api/v1/chat \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"assistantId": 1,
"message": "Какой у вас режим работы?",
"sessionId": "user-123"
}'Ответ
{
"id": "chatcmpl-abc123",
"content": "Мы работаем с 9:00 до 21:00 по московскому времени.",
"tokensUsed": 42,
"sessionId": "user-123",
"model": "gpt-4o-mini"
}Assistants
Управление ассистентами. Каждый ассистент — это ваш бот с настроенной инструкцией и базой знаний.
Список всех ваших ассистентов.
curl https://meerbot.ru/api/v1/assistants \ -H "Authorization: Bearer YOUR_API_KEY"
Информация о конкретном ассистенте.
curl https://meerbot.ru/api/v1/assistants/1 \ -H "Authorization: Bearer YOUR_API_KEY"
Knowledge
Загрузка базы знаний для ассистента. Поддерживаются текст, PDF, DOCX, TXT и URL.
Загрузить файл или текст в базу знаний ассистента.
# Загрузка текста
curl -X POST https://meerbot.ru/api/v1/knowledge \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"assistantId": 1,
"type": "text",
"content": "Наш магазин работает с 9:00 до 21:00."
}'
# Загрузка файла
curl -X POST https://meerbot.ru/api/v1/knowledge \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "assistantId=1" \
-F "file=@faq.pdf"Виджет на сайт (Web Chat SDK)
Бот живёт не только в Telegram. Веб-виджет встраивается на ваш сайт одним тегом <script> и подключается к тому же ассистенту: общая база знаний, общая инструкция, общая лента диалогов в кабинете.
pk_live_…. Готовый сниппет с вашим ключом лежит в кабинете на странице «Интеграции → Виджет» — просто скопируйте его.Минимальная установка
<!-- Положите перед </body> на любой странице сайта --> <script async src="https://widget.meerbot.ru/v0/loader.js" data-pk="pk_live_xxx" ></script>
Программная инициализация и идентификация
Вместо data-pk ключ и параметры можно задать через window.MeerBotSettings (имеет приоритет). Это же место для Intercom-style идентификации залогиненного пользователя — передайте externalUserId и его HMAC-подпись (считается на вашем бэкенде ключом виджета).
<script>
window.MeerBotSettings = {
pk: 'pk_live_xxx',
externalUserId: '42', // ваш ID пользователя (опционально)
externalHmac: '9f86d0…', // HMAC-SHA256 от externalUserId, подписанный на вашем бэкенде
// apiBase, containerId, zIndex — опционально, нужны редко
}
</script>
<script async src="https://widget.meerbot.ru/v0/loader.js"></script>JS API и события
Виджет публикует глобальный объект window.MeerBot с методами управления и подпиской на события — удобно для аналитики и CRM. Подписка на события включается флагом Events API в кабинете; в целях приватности payload сообщений содержит только метаданные (длина, локаль), без текста.
// Управление
MeerBot.open()
MeerBot.close()
MeerBot.destroy()
MeerBot.isReady // true, когда виджет готов
// События (требуют включённого Events API в кабинете)
const off = MeerBot.on('chat:open', () => analytics.track('chat_open'))
MeerBot.on('chat:close', () => analytics.track('chat_close'))
MeerBot.on('message:sent', (m) => console.log('длина:', m.length))
MeerBot.on('message:received', (m) => console.log('ответ, мета:', m))
MeerBot.on('escalation', (info) => console.log('передано менеджеру:', info))
MeerBot.on('unread', (n) => console.log('непрочитано:', n))
off() // отписатьсяЗащита и приватность
- JWT-токен сессии хранится в Redis с jti-allowlist — replay-атака отсекается.
- Per-IP rate-limit и опциональная Turnstile-проверка против ботов.
- CSP
frame-ancestors *разрешает встраивание, но XSS внутри виджета не пройдёт. - HMAC-сравнение через
crypto.timingSafeEqual— нет таймингового канала. - Загрузка файлов — за фичефлагом; если выключена в кабинете, серверная ручка просто 404.
pk_live_ не секретен — он специально нужен в HTML страницы. Доступ ограничен списком allowed-origins, биллинг и rate-limit считаются по бэкенду — выкрасть ключ и «слить токены» не получится.Telegram-бот
Подключите Telegram-бота к MeerBot, чтобы автоматически отвечать на вопросы ваших клиентов. Бот использует вашу базу знаний и инструкцию для генерации ответов.
Как подключить
- 1Создайте бота через @BotFather в Telegram (команда
/newbot) - 2Скопируйте токен бота (формат:
123456:ABC-DEF...) - 3Вставьте токен в личном кабинете → раздел «Telegram-бот»
- 4Бот автоматически подключится и начнёт отвечать на сообщения, используя вашу инструкцию и базу знаний
Как работает
1. Пользователь пишет в чат вашего бота в Telegram
2. MeerBot ищет релевантную информацию в вашей базе знаний (RAG-поиск)
3. AI генерирует ответ на основе найденного контекста и вашей инструкции
4. Ответ отправляется пользователю в Telegram
Единая лента (Multichannel Inbox)
Когда клиент пишет — в Telegram или через виджет на сайте — обращение попадает в одну ленту в кабинете. Менеджеру не нужно переключаться между вкладками: всё в /cabinet/inbox — с фильтром по каналу, бейджем непрочитанных и live-обновлением через SSE.
Поддерживаемые каналы
| Канал | Статус | Как подключить |
|---|---|---|
| Telegram | Готов | /cabinet/telegram-bot — токен → webhook |
| Сайт (виджет) | Готов | /cabinet/integrations — snippet кода |
| Скоро | Channel-абстракция уже готова, нужен canonical-провайдер | |
| VK | Скоро | Адаптер планируется |
| Avito | Скоро | Адаптер планируется |
Как работает
1. Клиент пишет в любой канал — Telegram-бот, виджет, в будущем WhatsApp/VK.
2. Сообщение попадает в общий поток ChannelEvents и в БД с пометкой канала.
3. AI отвечает по тем же правилам, что в Telegram — RAG + base prompt + внешние данные.
4. Менеджер в кабинете видит обращение в единой ленте и отвечает прямо оттуда, без открытия Telegram.
5. Backbone-абстракция канала позволяет добавить новый источник без переписывания UI.
Внешние данные клиента (API-источники)
AI отвечает релевантно, только когда видит контекст конкретного клиента — его тариф, заказы, баланс. MeerBot умеет ходить в ваш бэкенд и подмешивать данные в системный промпт до ответа модели, либо давать модели function-call и идти за данными по требованию.
Два режима
Платформа фетчит ваш API при первом сообщении в диалоге, рендерит результат человекочитаемым блоком и кладёт в системный промпт до того, как модель сгенерирует ответ.
Подходит: профиль клиента, тариф, оплаченные продукты.
Источник публикуется как OpenAI-совместимый tool. Модель сама решает, когда вызвать — например, чтобы найти заказ по номеру или создать тикет. До 3 раундов tool-call в одном ответе.
Подходит: поиск заказа, создание тикета, проверка остатков.
Шаблонизатор запроса
URL, query, headers поддерживают плейсхолдеры:
https://api.example.com/users/{user.id}
?email={user.email}
&plan={user.plan}
Заголовки:
X-Api-Key: {secret.SHOP_API_KEY} # шифруется AES-256-GCM
X-Request-Id: {request.id}user.* — Telegram-данные собеседника, secret.* — ваши секреты из кабинета (хранятся зашифрованными, никогда не светятся в логах).
Кэш и инвалидация
- Per-conversation cache в БД с TTL =
cacheTtlSec(по умолчанию 1 час). - Conditional-GET через сохранённый
ETag/Last-Modified— 304 не тратит токены и не насчитывает биллинг. - Принудительная инвалидация всех кешей источника — инкремент
cacheVersionв кабинете. - Менеджер в панели «Профиль клиента» видит тот же snapshot, что и LLM, и может перефетчить кнопкой.
Безопасность
- SSRF-валидатор: DNS-resolve + blocklist приватных подсетей (RFC-1918) + блоклист портов. Запрос к 127.0.0.1 или 10.0.0.1 не пройдёт.
- Шифрование секретов: AES-256-GCM на отдельном ключе
EXTERNAL_API_ENCRYPTION_SECRET. - Sanitizer ответа: deep-sanitize JSON от провайдера — никаких prompt-injection через поле «name».
- Circuit breaker: Redis-ключ блокирует источник на 5 минут при шторме 5xx — клиент не платит за неработающий API.
304 Not Modified бесплатен — ETag окупается на длинных диалогах.Mobile SDK
Для нативных приложений (iOS, Android, React Native) MeerBot отдаёт тройной SDK: на нативном Swift, на нативном Kotlin и на RN-мостах. Один и тот же ассистент — три варианта интеграции в зависимости от стека приложения.
Что в коробке
- Авторизация по publicId ассистента — тот же контракт, что у веб-виджета.
- Стриминг ответов AI через SSE — пользователь видит «печатание» как в Telegram.
- Вложения (фото, видео, документы), голосовые сообщения.
- Эскалация на менеджера — управляется тем же backend-флагом, что и в TG.
- Готовые UI-компоненты на платформенных нативных тулкитах (SwiftUI / Compose).
- Privacy manifest для App Store — поля декларации лежат рядом со SDK.
Эндпоинт
Mobile SDK ходит в тот же публичный эндпоинт, что и веб-виджет:
Конкретные методы SDK документируются в README каждого пакета — Swift, Kotlin и React Native. Для запроса SDK напишите в Telegram, мы выдадим приватный репозиторий и onboarding-инструкцию.
Группа поддержки
Telegram-группа поддержки — это место, куда бот перенаправляет сложные вопросы вашим менеджерам. Когда AI не может помочь, создаётся отдельный топик, и менеджер отвечает напрямую.
Настройка группы
- 1Создайте Telegram-группу (или используйте существующую)
- 2Включите Topics (Темы) в настройках группы — это обязательно
- 3Добавьте вашего бота в группу и назначьте его администратором (права: управление темами)
- 4Узнайте ID группы через @getidsbot и укажите его в настройках бота в кабинете
Как работает
1. Пользователь просит связаться с менеджером (или AI не уверен в ответе)
2. Бот спрашивает подтверждение: «Позвать менеджера?»
3. При подтверждении — создаётся топик в группе с контекстом диалога
4. Менеджер отвечает в топике — ответ автоматически пересылается пользователю
5. Команда /close в топике завершает обращение и возвращает бота в режим AI
Auth Bridge — вход с вашего сайта
Если у вас на сайте уже залогинены пользователи (есть email или внутренний ID), вы можете пробросить эту идентификацию в бот поддержки через подписанный токен в deep-link. Менеджер сразу увидит, кто пишет, и сможет открыть карточку пользователя в вашей админке одним кликом — а не вручную сопоставлять Telegram ID с записью в базе.
Шаг 1. Сгенерировать секрет в кабинете
- 1Откройте /cabinet/telegram-bot и найдите секцию «Авторизация с сайта (Auth Bridge)»
- 2Нажмите «Сгенерировать секрет» — мы создадим случайный ключ длиной 43 символа (256 бит энтропии)
- 3Скопируйте секрет сразу — повторно его показать нельзя. В кабинете останутся видны только последние 6 символов для опознания «тот же ключ или нет».
- 4Положите секрет в переменную окружения вашего сайта:
SUPPORT_AUTH_SECRET
Шаг 2. Подписать токен на стороне сайта
Когда залогиненный юзер кликает «Написать в поддержку», на сервере вашего сайта подпишите короткоживущий JWT и постройте deep-link:
https://t.me/<your_bot_username>?start=auth_<jwt>
Контракт JWT
Алгоритм: HS256. Токены с другим alg отбрасываются.
| Поле | Тип | Описание |
|---|---|---|
| sub | string | Ваш внутренний ID юзера. Обязателен. |
| string | Email юзера. Опционален, но хотя бы одно из email/externalId обязательно. | |
| externalId | string | Внутренний UUID юзера в вашей админке (panel_user_uuid, ID в БД и т.п.). Опционален. |
| iat | number | Unix timestamp выпуска (в секундах). |
| exp | number | Unix timestamp истечения. Рекомендуем iat + 60 секунд. |
Node.js — без зависимостей
import { createHmac } from 'node:crypto'
function base64url(buf) {
return buf.toString('base64')
.replace(/=+$/, '')
.replace(/\+/g, '-')
.replace(/\//g, '_')
}
export function buildSupportUrl(user) {
const secret = process.env.SUPPORT_AUTH_SECRET
if (!secret) return 'https://t.me/your_bot?start=guest'
const now = Math.floor(Date.now() / 1000)
const header = base64url(Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })))
const payload = base64url(Buffer.from(JSON.stringify({
sub: String(user.id),
email: user.email,
externalId: user.panelUuid,
iat: now,
exp: now + 60,
})))
const sig = base64url(
createHmac('sha256', secret).update(`${header}.${payload}`).digest()
)
return `https://t.me/your_bot?start=auth_${header}.${payload}.${sig}`
}Python — без зависимостей
import base64, hmac, hashlib, json, os, time
def _b64url(data: bytes) -> str:
return base64.urlsafe_b64encode(data).rstrip(b'=').decode()
def build_support_url(user: dict) -> str:
secret = os.environ.get('SUPPORT_AUTH_SECRET')
if not secret:
return 'https://t.me/your_bot?start=guest'
now = int(time.time())
header = _b64url(json.dumps({'alg': 'HS256', 'typ': 'JWT'}).encode())
payload = _b64url(json.dumps({
'sub': str(user['id']),
'email': user.get('email'),
'externalId': user.get('panel_uuid'),
'iat': now,
'exp': now + 60,
}).encode())
sig = _b64url(hmac.new(
secret.encode(),
f'{header}.{payload}'.encode(),
hashlib.sha256,
).digest())
return f'https://t.me/your_bot?start=auth_{header}.{payload}.{sig}'PHP
<?php
function b64url(string $data): string {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function build_support_url(array $user): string {
$secret = getenv('SUPPORT_AUTH_SECRET') ?: '';
if ($secret === '') return 'https://t.me/your_bot?start=guest';
$now = time();
$header = b64url(json_encode(['alg' => 'HS256', 'typ' => 'JWT']));
$payload = b64url(json_encode([
'sub' => (string)$user['id'],
'email' => $user['email'] ?? null,
'externalId' => $user['panel_uuid'] ?? null,
'iat' => $now,
'exp' => $now + 60,
]));
$sig = b64url(hash_hmac('sha256', "$header.$payload", $secret, true));
return "https://t.me/your_bot?start=auth_{$header}.{$payload}.{$sig}";
}Шаг 3. Шаблон ссылки на вашу админку
Чтобы кнопка «🛠 Открыть в админке» в кабинете и в форум-топике поддержки вела на нужную страницу, укажите URL-шаблон на странице /cabinet/telegram-bot с одним из плейсхолдеров:
| Плейсхолдер | Подставляется |
|---|---|
| {id} | Telegram user ID (доступен всегда) |
| {email} | Email из JWT (только если Auth Bridge активен) |
| {externalId} | externalId из JWT (только если Auth Bridge активен) |
Примеры рабочих шаблонов:
https://admin.example.com/users/{externalId}
https://admin.example.com/users?email={email}
https://crm.example.com/contact/{id}Можно указать два шаблона одновременно — менеджер увидит обе кнопки и выберет нужную. Удобно, если у вас в системе один юзер может объединять несколько Telegram-аккаунтов.
Гостевой режим (юзер не залогинен)
Если на сайте у юзера нет сессии — используйте URL без JWT:
https://t.me/your_bot?start=guest
Менеджер увидит бейдж «Гость» — это сигнал «пришёл с сайта, но не залогинен», что отличается от случайного человека, нашедшего бота через поиск.
Что увидит менеджер
| Бейдж | Когда показывается |
|---|---|
| Verified | Юзер пришёл с валидным непросроченным токеном |
| Expired | Токен валиден по подписи, но истёк (юзер мог открыть Telegram через минуту после клика) |
| Guest | Пришёл с сайта, но не залогинен (?start=guest) |
Рядом — email/externalId юзера и кнопки «🛠 Открыть в админке». Те же ссылки дублируются в сообщении о новом обращении в группе поддержки.
Безопасность
- Подписывайте JWT только на сервере. На клиенте секрет утечёт через DevTools.
- Не используйте библиотеки, поддерживающие
alg: none— мы такие токены отбрасываем, но плодить площадь атаки незачем. - TTL ≤ 60 секунд — это всё, что нужно для одного
/start. - Не кладите Telegram ID в
sub— он не известен сайту и приедет из самого update'а Telegram. Вsub— ваш внутренний идентификатор. - Ротация секрета — кнопка «Перегенерировать» в кабинете. Старый ключ мгновенно перестаёт работать; обновите env на сайте в той же сессии.
?start=auth_… откроет существующий чат без отправки /start. Identity не запишется. Это поведение самого Telegram. Для таких случаев менеджер может вбить email вручную в карточке клиента в кабинете.Эскалация на менеджера
Бот автоматически определяет, когда пользователь хочет поговорить с человеком, и перенаправляет диалог менеджеру в группу поддержки.
Когда срабатывает эскалация
Бот распознаёт 34 паттерна на русском и английском:
Если вопрос не покрывается базой знаний (низкий показатель similarity при RAG-поиске), бот предлагает связаться с менеджером. Порог настраивается.
Состояния диалога
| Режим | Описание |
|---|---|
| ai | Бот отвечает автоматически (основной режим) |
| pending_escalation | Бот спросил «Позвать менеджера?» — ждёт ответа пользователя |
| human | Менеджер отвечает в топике группы — бот пересылает сообщения |
| closed | Обращение завершено командой /close — бот возвращается в режим AI |
Ошибки
API использует стандартные HTTP-коды. Тело ошибки всегда содержит поле error.
| Код | Значение |
|---|---|
| 400 | Неверный запрос — проверьте параметры |
| 401 | Не авторизован — неверный или отсутствующий API-ключ |
| 404 | Ресурс не найден |
| 429 | Превышен лимит запросов |
| 500 | Внутренняя ошибка сервера |
Лимиты
Лимиты зависят от вашего тарифного плана. Текущие лимиты доступны в разделе тарифов.
SDK и примеры
MeerBot API совместим с OpenAI SDK. Используйте любой удобный инструмент.
Node.js
const response = await fetch('https://meerbot.ru/api/v1/chat', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
assistantId: 1,
message: 'Привет!',
sessionId: 'user-123',
}),
})
const { content } = await response.json()
console.log(content)Python
import requests
response = requests.post(
'https://meerbot.ru/api/v1/chat',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
json={
'assistantId': 1,
'message': 'Привет!',
'sessionId': 'user-123',
}
)
print(response.json()['content'])