API v1 · Стабильная версия

Документация API

REST API для интеграции MeerBot в ваш продукт. OpenAI-совместимый формат. Подходит для любого языка программирования.

Быстрый старт

Три шага, чтобы отправить первый запрос:

  1. 1Зарегистрируйтесь и создайте бота в личном кабинете
  2. 2Получите API-ключ в разделе «API-ключи»
  3. 3Отправьте запрос:
bash
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.

http
Authorization: Bearer YOUR_API_KEY
⚠️ Никогда не публикуйте API-ключ в клиентском коде. Все запросы к API должны идти через ваш бэкенд.

Chat

Отправка сообщений вашему ассистенту. Поддерживает сессии для многоходовых диалогов.

POST/api/v1/chat

Отправить сообщение и получить ответ ассистента.

Тело запроса

ПолеТипОписание
assistantIdnumberID ассистента. Обязательный.
messagestringТекст сообщения. Обязательный.
sessionIdstringID сессии для продолжения диалога. Опциональный.
bash
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"
  }'

Ответ

json
{
  "id": "chatcmpl-abc123",
  "content": "Мы работаем с 9:00 до 21:00 по московскому времени.",
  "tokensUsed": 42,
  "sessionId": "user-123",
  "model": "gpt-4o-mini"
}

Assistants

Управление ассистентами. Каждый ассистент — это ваш бот с настроенной инструкцией и базой знаний.

GET/api/v1/assistants

Список всех ваших ассистентов.

bash
curl https://meerbot.ru/api/v1/assistants \
  -H "Authorization: Bearer YOUR_API_KEY"
GET/api/v1/assistants/:id

Информация о конкретном ассистенте.

bash
curl https://meerbot.ru/api/v1/assistants/1 \
  -H "Authorization: Bearer YOUR_API_KEY"

Knowledge

Загрузка базы знаний для ассистента. Поддерживаются текст, PDF, DOCX, TXT и URL.

POST/api/v1/knowledge

Загрузить файл или текст в базу знаний ассистента.

bash
# Загрузка текста
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_…. Готовый сниппет с вашим ключом лежит в кабинете на странице «Интеграции → Виджет» — просто скопируйте его.

Минимальная установка

html
<!-- Положите перед </body> на любой странице сайта -->
<script
  async
  src="https://widget.meerbot.ru/v0/loader.js"
  data-pk="pk_live_xxx"
></script>
🎨 Внешний вид (тема, цвет, позиция, иконка, стартовые промпты, локаль, приём файлов, GDPR-согласие) настраивается в кабинете на странице виджета — эти параметры приходят с сервера по ключу, в HTML их дублировать не нужно.

Программная инициализация и идентификация

Вместо data-pk ключ и параметры можно задать через window.MeerBotSettings (имеет приоритет). Это же место для Intercom-style идентификации залогиненного пользователя — передайте externalUserId и его HMAC-подпись (считается на вашем бэкенде ключом виджета).

html
<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 сообщений содержит только метаданные (длина, локаль), без текста.

javascript
// Управление
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. 1Создайте бота через @BotFather в Telegram (команда /newbot)
  2. 2Скопируйте токен бота (формат: 123456:ABC-DEF...)
  3. 3Вставьте токен в личном кабинете → раздел «Telegram-бот»
  4. 4Бот автоматически подключится и начнёт отвечать на сообщения, используя вашу инструкцию и базу знаний

Как работает

1. Пользователь пишет в чат вашего бота в Telegram

2. MeerBot ищет релевантную информацию в вашей базе знаний (RAG-поиск)

3. AI генерирует ответ на основе найденного контекста и вашей инструкции

4. Ответ отправляется пользователю в Telegram

💡 Токен бота шифруется AES-256-GCM и никогда не хранится в открытом виде.

Единая лента (Multichannel Inbox)

Когда клиент пишет — в Telegram или через виджет на сайте — обращение попадает в одну ленту в кабинете. Менеджеру не нужно переключаться между вкладками: всё в /cabinet/inbox — с фильтром по каналу, бейджем непрочитанных и live-обновлением через SSE.

Поддерживаемые каналы

КаналСтатусКак подключить
TelegramГотов/cabinet/telegram-bot — токен → webhook
Сайт (виджет)Готов/cabinet/integrations — snippet кода
WhatsAppСкороChannel-абстракция уже готова, нужен canonical-провайдер
VKСкороАдаптер планируется
AvitoСкороАдаптер планируется

Как работает

1. Клиент пишет в любой канал — Telegram-бот, виджет, в будущем WhatsApp/VK.

2. Сообщение попадает в общий поток ChannelEvents и в БД с пометкой канала.

3. AI отвечает по тем же правилам, что в Telegram — RAG + base prompt + внешние данные.

4. Менеджер в кабинете видит обращение в единой ленте и отвечает прямо оттуда, без открытия Telegram.

5. Backbone-абстракция канала позволяет добавить новый источник без переписывания UI.

💡 Бейдж непрочитанных в сайдбаре кабинета — это первое, что менеджер видит на дашборде. SSE-канал держится открытым, push приходит без перезагрузки.

Внешние данные клиента (API-источники)

AI отвечает релевантно, только когда видит контекст конкретного клиента — его тариф, заказы, баланс. MeerBot умеет ходить в ваш бэкенд и подмешивать данные в системный промпт до ответа модели, либо давать модели function-call и идти за данными по требованию.

💡 Управление источниками — в кабинете на странице /cabinet/api-sources. До 10 источников на бот, до 5 одновременно включённых.

Два режима

contextПодмешать перед ответом

Платформа фетчит ваш API при первом сообщении в диалоге, рендерит результат человекочитаемым блоком и кладёт в системный промпт до того, как модель сгенерирует ответ.

Подходит: профиль клиента, тариф, оплаченные продукты.

toolВызов по требованию

Источник публикуется как OpenAI-совместимый tool. Модель сама решает, когда вызвать — например, чтобы найти заказ по номеру или создать тикет. До 3 раундов tool-call в одном ответе.

Подходит: поиск заказа, создание тикета, проверка остатков.

Шаблонизатор запроса

URL, query, headers поддерживают плейсхолдеры:

text
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.
⚠️ Каждый успешный фетч списывается с баланса по фактической стоимости (HTTP-latency × markup). Условный 304 Not Modified бесплатен — ETag окупается на длинных диалогах.

Mobile SDK

Для нативных приложений (iOS, Android, React Native) MeerBot отдаёт тройной SDK: на нативном Swift, на нативном Kotlin и на RN-мостах. Один и тот же ассистент — три варианта интеграции в зависимости от стека приложения.

💡 Mobile SDK на этапе foundation — backend готов, SDK-пакеты выложены в кабинет клиента. Production-grade Sample-приложения в работе.

Что в коробке

  • Авторизация по publicId ассистента — тот же контракт, что у веб-виджета.
  • Стриминг ответов AI через SSE — пользователь видит «печатание» как в Telegram.
  • Вложения (фото, видео, документы), голосовые сообщения.
  • Эскалация на менеджера — управляется тем же backend-флагом, что и в TG.
  • Готовые UI-компоненты на платформенных нативных тулкитах (SwiftUI / Compose).
  • Privacy manifest для App Store — поля декларации лежат рядом со SDK.

Эндпоинт

Mobile SDK ходит в тот же публичный эндпоинт, что и веб-виджет:

POST/api/v1/mobile/chat

Конкретные методы SDK документируются в README каждого пакета — Swift, Kotlin и React Native. Для запроса SDK напишите в Telegram, мы выдадим приватный репозиторий и onboarding-инструкцию.

Хотите Mobile SDK раньше остальных?
Напишите — выдадим доступ к private-репозиторию и поможем со встройкой.
Запросить SDK

Группа поддержки

Telegram-группа поддержки — это место, куда бот перенаправляет сложные вопросы вашим менеджерам. Когда AI не может помочь, создаётся отдельный топик, и менеджер отвечает напрямую.

Настройка группы

  1. 1Создайте Telegram-группу (или используйте существующую)
  2. 2Включите Topics (Темы) в настройках группы — это обязательно
  3. 3Добавьте вашего бота в группу и назначьте его администратором (права: управление темами)
  4. 4Узнайте ID группы через @getidsbot и укажите его в настройках бота в кабинете

Как работает

1. Пользователь просит связаться с менеджером (или AI не уверен в ответе)

2. Бот спрашивает подтверждение: «Позвать менеджера?»

3. При подтверждении — создаётся топик в группе с контекстом диалога

4. Менеджер отвечает в топике — ответ автоматически пересылается пользователю

5. Команда /close в топике завершает обращение и возвращает бота в режим AI

Auth Bridge — вход с вашего сайта

Если у вас на сайте уже залогинены пользователи (есть email или внутренний ID), вы можете пробросить эту идентификацию в бот поддержки через подписанный токен в deep-link. Менеджер сразу увидит, кто пишет, и сможет открыть карточку пользователя в вашей админке одним кликом — а не вручную сопоставлять Telegram ID с записью в базе.

💡 Фича опциональная. Нужна только если у вас есть собственная админка пользователей, в которой менеджер хочет находить клиента по email / внутреннему ID.

Шаг 1. Сгенерировать секрет в кабинете

  1. 1Откройте /cabinet/telegram-bot и найдите секцию «Авторизация с сайта (Auth Bridge)»
  2. 2Нажмите «Сгенерировать секрет» — мы создадим случайный ключ длиной 43 символа (256 бит энтропии)
  3. 3Скопируйте секрет сразу — повторно его показать нельзя. В кабинете останутся видны только последние 6 символов для опознания «тот же ключ или нет».
  4. 4Положите секрет в переменную окружения вашего сайта: SUPPORT_AUTH_SECRET
⚠️ Секрет — это HMAC-ключ. Храните его только на сервере: в env-переменных, Vault, секрет-менеджере. Никогда не кладите в клиентский код, в публичные репозитории, в логи или в Sentry.

Шаг 2. Подписать токен на стороне сайта

Когда залогиненный юзер кликает «Написать в поддержку», на сервере вашего сайта подпишите короткоживущий JWT и постройте deep-link:

text
https://t.me/<your_bot_username>?start=auth_<jwt>

Контракт JWT

Алгоритм: HS256. Токены с другим alg отбрасываются.

ПолеТипОписание
substringВаш внутренний ID юзера. Обязателен.
emailstringEmail юзера. Опционален, но хотя бы одно из email/externalId обязательно.
externalIdstringВнутренний UUID юзера в вашей админке (panel_user_uuid, ID в БД и т.п.). Опционален.
iatnumberUnix timestamp выпуска (в секундах).
expnumberUnix timestamp истечения. Рекомендуем iat + 60 секунд.
⏱️ TTL должен быть коротким (60 секунд достаточно). Токен нужен только на промежуток «клик в браузере → открытие Telegram → отправка /start». Длинный TTL увеличивает окно для replay-атаки без выигрыша.

Node.js — без зависимостей

javascript
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 — без зависимостей

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
<?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 активен)

Примеры рабочих шаблонов:

text
https://admin.example.com/users/{externalId}
https://admin.example.com/users?email={email}
https://crm.example.com/contact/{id}

Можно указать два шаблона одновременно — менеджер увидит обе кнопки и выберет нужную. Удобно, если у вас в системе один юзер может объединять несколько Telegram-аккаунтов.

Гостевой режим (юзер не залогинен)

Если на сайте у юзера нет сессии — используйте URL без JWT:

text
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 на сайте в той же сессии.
⚠️ Известное ограничение Telegram: если у юзера с ботом уже открыт диалог, повторный клик по ?start=auth_… откроет существующий чат без отправки /start. Identity не запишется. Это поведение самого Telegram. Для таких случаев менеджер может вбить email вручную в карточке клиента в кабинете.

Эскалация на менеджера

Бот автоматически определяет, когда пользователь хочет поговорить с человеком, и перенаправляет диалог менеджеру в группу поддержки.

Когда срабатывает эскалация

Явный запрос пользователя

Бот распознаёт 34 паттерна на русском и английском:

позови менеджераоператорхочу человекаподдержкаlive agentspeak to humanи другие...
Низкая уверенность AI

Если вопрос не покрывается базой знаний (низкий показатель similarity при RAG-поиске), бот предлагает связаться с менеджером. Порог настраивается.

Состояния диалога

РежимОписание
aiБот отвечает автоматически (основной режим)
pending_escalationБот спросил «Позвать менеджера?» — ждёт ответа пользователя
humanМенеджер отвечает в топике группы — бот пересылает сообщения
closedОбращение завершено командой /close — бот возвращается в режим AI
⏱️ Если менеджер не отвечает 30 минут — бот автоматически возвращается в режим AI, чтобы пользователь не остался без ответа.

Ошибки

API использует стандартные HTTP-коды. Тело ошибки всегда содержит поле error.

КодЗначение
400Неверный запрос — проверьте параметры
401Не авторизован — неверный или отсутствующий API-ключ
404Ресурс не найден
429Превышен лимит запросов
500Внутренняя ошибка сервера

Лимиты

Лимиты зависят от вашего тарифного плана. Текущие лимиты доступны в разделе тарифов.

60
Запросов в минуту
4 000 симв.
Макс. длина сообщения
10 MB
Макс. размер файла

SDK и примеры

MeerBot API совместим с OpenAI SDK. Используйте любой удобный инструмент.

Node.js

javascript
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

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'])
Нужна помощь с интеграцией?
Напишите нам — поможем подключить API к вашему проекту.
Написать в Telegram