Bot API VVelcom.online
Боты — это программы, которые общаются с людьми в VVelcom: отвечают на команды, присылают уведомления, принимают заказы, открывают свои мини-приложения прямо в мессенджере. Бот работает на вашем сервере и разговаривает с VVelcom по простому HTTP API.
Создавая бота, вы принимаете Условия для разработчиков ботов и несёте ответственность за бота, его токен, мини-приложение и данные пользователей.
Уже есть бот в Telegram?
API сделан дружелюбным к Telegram: те же методы, те же поля, тот же адрес вида
/bot<токен>/<метод>. Чтобы перенести бота, обычно достаточно получить токен у
@VVbotMother и поменять адрес API в вашей библиотеке
(grammY, aiogram, node-telegram-bot-api и другие). После переноса проверьте используемые
методы по разделу «Чем отличается»: Bot API совместим не со всеми возможностями Telegram.
Никакие данные при этом в Telegram не передаются — это только совместимый формат.
Быстрый старт
Хотите начать с готового проекта? Возьмите пример на нужном языке, заполните
.env и запустите его по инструкции.
-
Найдите @VVbotMother
Это бот, который создаёт других ботов. Откройте его в приложении VVelcom — в поиске
наберите
VVbotMotherили перейдите по ссылке: -
Создайте бота
Нажмите «Начать» и отправьте
/newbot— или нажмите «Открыть» и создайте бота в приложении VVbotMother. Придумайте имя (его видят пользователи) и username — адрес бота.Правило для username Латиница, цифры и_, от 6 до 32 символов, начинается с буквы и обязательно заканчивается наvvbot(регистр любой):weather_vvbot,ShopVVbot,my_helper_vvbot. -
Скопируйте токен
В ответ придёт токен вида
vv_AbC123…— нажмите на него, чтобы скопировать. Посмотреть токен снова — команда/token, выпустить новый —/revoke.Токен — это пароль бота С ним кто угодно может управлять ботом. Не публикуйте его в коде на GitHub и в чатах; храните в переменной окружения. -
Проверьте, что всё работает
Откройте в браузере (подставьте свой токен) или выполните в терминале:
В ответ придётcurl https://apibots.vvelcom.online/botvv_ВАШ_ТОКЕН/getMe{"ok":true,"result":{…}}с данными вашего бота. - Напишите код бота Готовый пример на 20 строк — в следующем разделе. Запустите его, откройте своего бота в VVelcom, нажмите «Начать» — и он ответит.
Первый бот
Эхо-бот: отвечает на /start приветствием, а на любое другое сообщение — его же текстом.
Он забирает новые сообщения методом getUpdates, поэтому ему не нужен ни публичный
сервер, ни домен — можно запустить прямо на своём компьютере.
// bot.mjs — Node.js 18+, без зависимостей. Запуск: BOT_TOKEN=vv_… node bot.mjs
const API = `https://apibots.vvelcom.online/bot${process.env.BOT_TOKEN}`;
async function call(method, params = {}) {
const res = await fetch(`${API}/${method}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params),
});
const data = await res.json();
if (!data.ok) throw new Error(data.description);
return data.result;
}
let offset = 0;
while (true) {
// Ждём новые события до 30 секунд (long polling)
const updates = await call('getUpdates', { offset, timeout: 30 });
for (const update of updates) {
offset = update.update_id + 1; // подтверждаем обработанное
const msg = update.message;
if (!msg?.text) continue;
const text = msg.text === '/start'
? 'Привет! Я эхо-бот. Напишите мне что-нибудь.'
: `Вы написали: ${msg.text}`;
await call('sendMessage', { chat_id: msg.chat.id, text });
}
}
# bot.py — Python 3.8+, нужен requests (pip install requests). Запуск: BOT_TOKEN=vv_… python bot.py
import os, requests
API = f"https://apibots.vvelcom.online/bot{os.environ['BOT_TOKEN']}"
def call(method, **params):
data = requests.post(f"{API}/{method}", json=params, timeout=60).json()
if not data["ok"]:
raise RuntimeError(data["description"])
return data["result"]
offset = 0
while True:
for update in call("getUpdates", offset=offset, timeout=30):
offset = update["update_id"] + 1
msg = update.get("message")
if not msg or not msg.get("text"):
continue
text = ("Привет! Я эхо-бот. Напишите мне что-нибудь."
if msg["text"] == "/start" else f"Вы написали: {msg['text']}")
call("sendMessage", chat_id=msg["chat"]["id"], text=text)
// npm i grammy — та же библиотека, что для Telegram, меняется только apiRoot
import { Bot } from 'grammy';
const bot = new Bot(process.env.BOT_TOKEN, {
client: { apiRoot: 'https://apibots.vvelcom.online' },
});
bot.command('start', (ctx) => ctx.reply('Привет! Я эхо-бот.'));
bot.on('message:text', (ctx) => ctx.reply(`Вы написали: ${ctx.message.text}`));
bot.start();
# pip install aiogram — меняется только адрес сервера
import asyncio, os
from aiogram import Bot, Dispatcher, F
from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.client.telegram import TelegramAPIServer
from aiogram.filters import CommandStart
session = AiohttpSession(api=TelegramAPIServer.from_base("https://apibots.vvelcom.online"))
bot = Bot(os.environ["BOT_TOKEN"], session=session)
dp = Dispatcher()
@dp.message(CommandStart())
async def start(message):
await message.answer("Привет! Я эхо-бот.")
@dp.message(F.text)
async def echo(message):
await message.answer(f"Вы написали: {message.text}")
asyncio.run(dp.start_polling(bot))
Дальше можно добавить команды в кнопку «Меню» (setMyCommands),
кнопки под сообщениями (inline-клавиатура) и мини-приложение
(веб-страница внутри мессенджера).
Как бот получает сообщения
Всё, что происходит с ботом — новое сообщение, нажатие кнопки, добавление в группу, — приходит
ему событием (Update). У каждого события свой номер update_id,
события идут строго по порядку. Забирать их можно одним из двух способов:
| getUpdates (long polling) | Webhook | |
|---|---|---|
| Как работает | Бот сам спрашивает «есть что-то новое?» и ждёт ответа до timeout секунд | Мы сами присылаем каждое событие POST-запросом на ваш URL |
| Что нужно | Ничего — работает с любого компьютера | Публичный HTTPS-адрес |
| Когда выбрать | Разработка, небольшие боты | Боевой режим, много пользователей |
Одновременно работает только один способ: пока задан webhook, getUpdates вернёт ошибку
409. Неполученные события хранятся 24 часа.
Webhook за три шага
# 1. Сообщаем адрес (и секрет, по которому вы будете узнавать наши запросы)
curl -X POST https://apibots.vvelcom.online/botvv_ВАШ_ТОКЕН/setWebhook \
-H 'Content-Type: application/json' \
-d '{"url": "https://bot.example.com/webhook", "secret_token": "my-secret-123"}'
// 2. Принимаем события — Node.js + Express
import express from 'express';
const app = express();
app.use(express.json());
app.post('/webhook', async (req, res) => {
// Проверяем, что запрос пришёл от VVelcom
if (req.get('X-Telegram-Bot-Api-Secret-Token') !== 'my-secret-123') return res.sendStatus(403);
res.sendStatus(200); // 3. Отвечаем 2xx быстро — иначе событие придёт повторно
const msg = req.body.message;
if (msg?.text) await call('sendMessage', { chat_id: msg.chat.id, text: 'Получил!' });
});
app.listen(8443);
- Адрес — только
https, порты 443 или 8443, только публичный хост (не localhost и не локальная сеть). Порт 8443 — просто запасной HTTPS-порт для вашего сервера, кgetUpdatesон отношения не имеет. - Секрет (
secret_token) приходит в заголовкахX-Messenger-Webhook-Secret(VVelcom) иX-Telegram-Bot-Api-Secret-Token(для Telegram-библиотек) — значение одно и то же. - Ответ
2xxнужен в течение 10 секунд. При ошибке, таймауте,5xxили429событие придёт снова: через 1 мин, 5 мин, 15 мин, 1 ч, 6 ч и 24 ч. Ответ4xx(кроме 429) не повторяется. - После 20 ошибок подряд доставка встаёт на паузу, а @VVbotMother присылает вам сообщение. Исправьте сервер и вызовите
setWebhookещё раз. - Одно и то же событие может прийти дважды при сбое сети — обрабатывайте события по
update_idодин раз.
Запросы и ответы
Адрес
https://apibots.vvelcom.online/bot<токен>/<метод>
Токен начинается с vv_, поэтому в адресе получается …/botvv_AbC…/getMe — это
тот формат, который собирают библиотеки для Telegram. Можно передавать токен
и заголовком: https://apibots.vvelcom.online/bot-api/<метод> +
Authorization: Bearer vv_….
Параметры
- JSON в теле (
Content-Type: application/json), форма (x-www-form-urlencoded,multipart/form-data) или query-строка — как удобнее. Файл можно приложить только вsendPhoto/sendVideo. - Подходит любой HTTP-метод (GET, POST…), имя метода — без учёта регистра.
- Вложенные объекты в форме (например,
reply_markup) передаются JSON-строкой.
Ответ
// успех
{ "ok": true, "result": { … } }
// ошибка — HTTP-статус совпадает с error_code
{ "ok": false, "error_code": 400, "description": "Bad Request: text is required" }
| Код | Что значит |
|---|---|
400 | Неверные параметры — подробности в description |
401 | Неверный или отозванный токен |
403 | Писать в этот чат нельзя (пользователь не начинал диалог, бота удалили из группы) |
409 | getUpdates при включённом webhook |
429 | Слишком много запросов — подождите |
Лимиты
- 30 запросов в секунду на бота;
- 60 сообщений в минуту в один чат;
- 20 фото и видео в минуту на бота;
- текст длиннее 4096 символов уходит несколькими сообщениями — каждое считается отдельно в лимите на чат.
Где бот может писать
- Личный чат — только после того, как пользователь сам начал диалог: нажал «Начать» или написал боту. Первым написать незнакомому человеку бот не может.
-
Группа — если бота добавили в группу. В поток новых событий бот автоматически
получает только обращённые к нему сообщения:
упоминание
@username_бота, команду/cmdили/cmd@username_ботаи ответ (reply) на своё сообщение. Добавление бота в группу разрешает ему работать с доступной историей этой группы, включая поиск черезsearchChatMessages. Это явный запрос API, а не автоматическая передача всей переписки. После удаления бота из группы доступ прекращается сразу. - Канал — если бота добавили в канал. Там бот администратор: публикует посты от имени канала (
sendMessage,sendPhoto,sendVideo) и получает каждый новый пост событиемchannel_post. Вchat_idканал можно указать ником:"chat_id": "@my_channel"— как в Telegram. Это работает во всех методах и только для канала, в котором бот состоит; иначе —403 BOT_CHAT_ACCESS_DENIED. - Комментарии к посту —
sendMessage,sendPhotoилиsendVideoсchat_idканала иcomment_to_message_id= id поста. Сообщения в обсуждении, адресованные боту, приходят какmessageс полемcomment_to_message— текстом самого поста (см. события).
Бот не видит телефон, email и список чатов пользователя. Без отдельного разрешения пользователя он
не может читать чаты, в которых сам не состоит. О человеке бот видит имя, фамилию, username и фото профиля (photo_url, метод getUserProfilePhotos), если человек показывает фото всем. Его id — случайный и свой для каждого бота, настоящий id в мессенджере бот не видит.
Доступ к боту
Настраивается в мини-приложении @VVbotMother: карточка бота → «Доступ». Проверяет всё платформа — вашему коду ничего делать не нужно.
- Кто может пользоваться — «Все» или «Только я и выбранные люди» (закрытое тестирование). Людей добавляют по
@нику, до 100 человек. Тем, кого нет в списке, в личном чате приходит ответ «бот в закрытом тестировании», а бот не получает ниmessage, ниbot_started; их упоминания в группах, нажатия кнопок и запуск мини-приложения до бота тоже не доходят. - Можно добавлять в группы и каналы — если выключить, бот сразу выходит из группы или канала, куда его добавили, и из всех, где он уже есть. Выход приходит событием
my_chat_memberсо статусомleft. - Видит всю переписку группы — бот получает событием
messageкаждое сообщение групп, где он состоит, а не только обращения к нему. Аналог выключенного Group Privacy в Telegram. Участники видят под ботом в информации о группе пометку «Видит все сообщения группы». - Общение с другими ботами — бот получает сообщения других ботов (
from.is_bot: true) в группах и напрямую: написать другому боту можно по нику,sendMessage { chat_id: "@other_vvbot", text }, — личный чат откроется сам, если общение с ботами включено у обоих. Защита от зацикливания: в чате подряд проходит не больше 10 сообщений ботов (счёт обнуляется, когда пишет человек, или через 10 минут тишины) и не больше 20 в минуту на бота-получателя. - Политика конфиденциальности — ссылка на страницу о том, какие данные собирает бот. Её видно в карточке бота и в окне перед первым открытием мини-приложения.
Ветки
Включаются владельцем в @VVbotMother: «Настройки бота» → «Ветки» → «Ветки в личном чате». В личном чате с ботом появляется переключатель веток — отдельных разговоров, например по одному на задачу («Общая / ветки / + Ветка»). Сообщения из ветки приходят с message_thread_id и is_topic_message: true; ответить в ветку — передать message_thread_id в методы отправки. Ветками бот управляет методами createForumTopic, editForumTopic, deleteForumTopic и getForumTopics — как темами в Telegram.
Ветки бывают только в личном чате с ботом; в группах message_thread_id не поддерживается. Неизвестная ветка — 400 Bad Request: message thread not found. Название ветки — до 64 символов, веток на чат — до 100; deleteForumTopic не удаляет сообщения, в приложении они остаются в «Общей». getMe возвращает has_topics_enabled и allows_users_to_create_topics. Переключатель «Запретить людям создавать ветки» убирает у людей кнопку «+ Ветка»: ветки создаёт только бот через createForumTopic (как «Disallow users to create new threads» в BotFather).
Ответ по ходу
Пока бот готовит ответ — ждёт нейросеть, распознаёт голосовое, считает, — человек видит, как ответ печатается, а не одно сообщение в конце. Это sendMessageDraft, как в Telegram. Работает в личных чатах и группах (не в каналах), в любом боте, отдельно включать не нужно; ветки для этого тоже не нужны (message_thread_id — только если отвечаете в ветку).
POST sendMessageDraft { "chat_id": "…", "draft_id": 42, "text": "Составляю список:\n• Молоко" }
draft_id — любое ненулевое число (или короткая строка A-Za-z0-9_-), одно на ответ. Каждый вызов с тем же draft_id заменяет текст целиком — передавайте весь текст на данный момент. Черновик — пузырь от бота внизу чата с мигающим курсором; он исчезает, когда бот присылает готовое сообщение (sendMessage и т. п.), при пустом text или через 30 секунд без обновлений. Ничего не сохраняется: в историю и в push черновик не попадает. Не чаще 30 обновлений за 3 секунды на чат (лишние отбрасываются), разумный шаг — раз в 0,5–1 с. Текст — до 4096 символов, разметка (parse_mode, entities) не применяется: оформление — в готовом сообщении.
Каким ИИ отвечать, решаете вы на своём сервере: платформа ключей нейросетей не хранит и сама за бота не отвечает. Типичная схема с потоковым API модели (stream: true): копите текст из кусочков, раз в ~0,7 с отправляйте его в sendMessageDraft, в конце — sendMessage с готовым ответом.
Режимы бота
Три режима, как в Telegram. Владелец включает их в @VVbotMother: «Настройки бота» → «Режимы».
getMe отвечает can_connect_to_business (секретарь) и supports_inline_queries (запросы через @).
Режим секретаря. Человек выбирает бота ассистентом: «Профиль → Секретари», меню «⋮» списка чатов или чата.
Выбрать можно только бота, которого человек запустил сам. Работает в личных чатах и обычных группах. Бот получает
business_connection (подключили или отключили) и business_message (сообщение другого человека в чате;
вид как у message плюс business_connection_id). Отвечать надо sendMessage с
chat_id и business_connection_id — сообщение уйдёт от имени человека, а он увидит под ним «Ответил бот @имя».
Если бот больше не ассистент — 403. Текущее состояние — getBusinessConnection.
Запросы через @ (inline). Человек пишет «@бот запрос» в любом чате. Бот получает
inline_query и за 10 секунд отвечает answerInlineQuery (до 50 результатов, cache_time до 3600 с).
Выбранный результат человек отправляет от себя с пометкой «via @бот», бот получает chosen_inline_result.
Подсказку в поле ввода задаёт владелец.
Гостевой режим. Бота зовут упоминанием @бот в чат, где его нет (личный или группа). Бот видит только это
сообщение — оно приходит как message с guest_mode: true. Ответить sendMessage можно в течение
15 минут, до 5 сообщений, без кнопок; ответ уходит от имени позвавшего с пометкой «via @бот».
Настройки бота в группах
Видит всю переписку группы. Бот получает все сообщения групп, где он состоит, а не только упоминания, команды и ответы на его сообщения. Нужно для модерации и сводок; участники группы видят рядом с ботом пометку «видит все сообщения».
Общение с другими ботами. Бот получает сообщения других ботов в группах и напрямую (если включено у обоих). Чтобы боты не отвечали друг другу бесконечно, подряд проходит не больше 10 сообщений ботов — дальше пауза, пока не напишет человек или не пройдёт 10 минут; и не больше 20 в минуту.
Можно добавлять в группы и каналы. Если выключить, бот сразу выйдет из всех групп и каналов, куда его добавят.
Методы
Все методы вызываются одинаково: POST https://apibots.vvelcom.online/bot<токен>/<метод> с JSON-телом.
Сообщения
getMe
Проверяет токен и возвращает информацию о боте. Параметров нет.
sendMessage
Отправляет текстовое сообщение.
| Параметр | Тип | Описание |
|---|---|---|
chat_id | string | id чата — берётся из события: message.chat.id. Для канала можно передать @ник |
text | string | Текст любой длины; длиннее 4096 символов отправляется несколькими сообщениями (кнопки — на последнем) |
reply_markup | object | Необязательно. Кнопки: inline_keyboard, keyboard или remove_keyboard — см. Кнопки |
reply_to_message_id | string | Необязательно. Ответить на сообщение (также принимается reply_parameters.message_id) |
comment_to_message_id | string | Только для канала: написать комментарий под этим постом |
{
"chat_id": "7eb76e3b-28c4-470d-b799-7c540e4972fc",
"text": "Привет! Чем могу помочь?",
"reply_markup": {
"inline_keyboard": [[{ "text": "Показать меню", "callback_data": "menu" }]]
}
}
Возвращает отправленное сообщение (Message).
sendPhoto / sendVideo
Отправляют фото или видео — обычное сообщение с вложением. Платформа сама сжимает файл, как приложение сжимает отправляемое людьми: фото — до 1280 px по длинной стороне, JPEG (метаданные EXIF удаляются); видео — до 1280 px, H.264 + AAC в MP4. Для обоих делается размытое превью, файл шифруется и загружается в хранилище.
| Параметр | Тип | Описание |
|---|---|---|
chat_id | string | id чата или @ник канала, в котором бот состоит |
photo / video | string или файл | https-ссылка на файл (платформа скачает его сама) или файл в multipart/form-data в поле с этим именем. Фото — до 20 МБ (JPEG, PNG, WebP, GIF, AVIF, TIFF), видео — до 200 МБ и 10 минут |
caption | string | Необязательно. Подпись; первые 4096 символов идут под файлом, остаток — следующими сообщениями |
reply_to_message_id | string | Необязательно. Ответить на сообщение |
comment_to_message_id | string | Только для канала: фото или видео комментарием под постом |
{
"chat_id": "@my_channel",
"photo": "https://example.com/cat.jpg",
"caption": "Кот"
}
Возвращает отправленное сообщение с caption и photo либо video. Ссылка — только https, порты 443 и 8443, без редиректов и частных адресов.
Пока без reply_markup и альбомов; текст такого сообщения не редактируется (editMessageText вернёт 400). Лимит — 20 фото и видео в минуту на бота.
editMessageText
{ chat_id, message_id, text, reply_markup? } — меняет текст и inline-кнопки своего сообщения.
Если reply_markup не передан, кнопки убираются. Удобно, чтобы менять экран «меню» по нажатию кнопки, не засоряя чат новыми сообщениями.
deleteMessage · sendChatAction
deleteMessage { chat_id, message_id } удаляет сообщение бота. sendChatAction принимается для совместимости и ничего не делает.
answerCallbackQuery
{ callback_query_id, text?, show_alert? } — ответ на нажатие inline-кнопки. text (до 200 символов)
пользователь увидит подсказкой, а с show_alert: true — окном. Отвечайте в течение ~5 секунд,
пока у кнопки крутится индикатор.
События и webhook
getUpdates
{ offset?, limit? (1–100), timeout? (до 50 с), allowed_updates? } — забрать новые события.
offset = последний update_id + 1 подтверждает всё, что было раньше: эти события больше не вернутся.
С timeout запрос ждёт, пока не появится новое событие.
setWebhook
{ url, secret_token?, drop_pending_updates?, allowed_updates? } — включить доставку событий на ваш адрес.
secret_token — 1–256 символов A-Z a-z 0-9 _ -, приходит в заголовке каждого запроса.
Повторный вызов снимает паузу доставки. Подробнее — в разделе Как бот получает сообщения.
deleteWebhook
{ drop_pending_updates? } — выключить webhook (например, чтобы перейти на getUpdates).
getWebhookInfo
Состояние webhook: адрес, сколько событий ждёт доставки, последняя ошибка.
{ "ok": true, "result": {
"url": "https://bot.example.com/webhook", "has_secret_token": true,
"pending_update_count": 0, "last_error_message": null
} }
Команды и меню
setMyCommands · getMyCommands · deleteMyCommands
Список команд, который пользователи видят в кнопке «Меню» и в подсказках, когда набирают /.
До 100 команд; команда — a-z 0-9 _ до 32 символов, описание — до 256.
Через setMyCommands команды видны везде. Чтобы показать команду только в части чатов, настройте её в
@VVbotMother («Мои боты» → «Команды») в блоке «Кто видит»: «Личные чаты» (чат с ботом 1 на 1), «Групповые чаты»,
«Администраторы групп» (команда только для владельца и админов группы) и «Пространства» (чаты внутри обычных
пространств; в глобальных чатах настройка не действует). Это только отображение в списке «/» и в «Меню»:
команда, введённая вручную, дойдёт до бота в любом случае. Повторный setMyCommands заменяет список и
сбрасывает эти настройки.
{ "commands": [
{ "command": "start", "description": "Начать" },
{ "command": "help", "description": "Помощь" }
] }
setChatMenuButton · getChatMenuButton
Что делает кнопка слева от поля ввода в чате с ботом. { chat_id?, menu_button }, где menu_button:
{ "type": "commands" }— «Меню» со списком команд;{ "type": "web_app", "text": "Открыть", "web_app": { "url": "https://…" } }— кнопка открывает мини-приложение;{ "type": "default" }— сбросить.
Без chat_id — для всех чатов, с chat_id — только для этого.
answerWebAppQuery
{ web_app_query_id, result: { type: "article", id, title, input_message_content: { message_text } } } —
отправить сообщение в чат, из которого открыли мини-приложение, и закрыть его окно.
web_app_query_id — это query_id из initData. Сообщение приходит от имени бота.
Чаты и пространства
Добавление бота в пространство не открывает ему все закрытые чаты: бот видит только чаты, в которых состоит,
и публичные чаты (открытые группы и каналы) пространства, в которое его добавили. Доступ проверяется при каждом
запросе, а не по ранее полученному списку чатов или сохранённому chat_id: после удаления бота
из группы или пространства следующий запрос уже получит отказ. Закрытые группы без бота и чаты других
пространств недоступны. Искать людей по всему мессенджеру бот не может, а историю группы он видит по её
правилам для новых участников.
Отказ приходит как 403 с полем code: BOT_CHAT_ACCESS_DENIED (нет доступа к чату)
или BOT_SPACE_ACCESS_DENIED (нет доступа к пространству). Для чата, которого нет, и чата, который боту
видеть нельзя, ответ одинаковый.
| Метод | Что возвращает |
|---|---|
getChat { chat_id } | Чат: id, type, title, description, space_id, member_count. Для участника и для публичного чата |
getChatMemberCount { chat_id } | Число участников (только чат, где бот состоит) |
getChatMember { chat_id, user_id } | Участник и его роль: creator | administrator | member | left; user_id — id человека для вашего бота (только чат, где бот состоит) |
getChatAdministrators { chat_id } | Администраторы (только чат, где бот состоит) |
getChatMembers { chat_id, query?, offset?, limit? } | Участники (люди — с именем, фамилией и username под своим id для вашего бота; поиск по имени работает среди ботов; только чат, где бот состоит) |
searchChatMessages { chat_id, query, limit?, offset? } | Явный поиск по доступной боту истории чата: где бот состоит, либо в публичном (открытом) чате пространства, в которое его добавили. Иначе 403 BOT_CHAT_ACCESS_DENIED. До 20 поисков в минуту. Новые сообщения без обращения к боту при этом не становятся событиями. |
readUserChat { user_id, chat_id, query?, limit?, offset?, from_user_id? } | Прочитать чат, где бота нет, с разрешения человека. Первый вызов отправляет человеку вопрос (в его чате с ботом) и отвечает 403 с parameters.request_id; после «Разрешить» придёт событие chat_access, и повторный вызов вернёт { messages, next_offset }. Доступ — на 24 часа, только к этому чату и только к тому, что видит сам человек. Не больше 3 вопросов в час одному человеку. |
sendSpaceAnnouncement { space_id, text } | Системное уведомление для всего пространства. Доступно боту, добавленному в пространство; права администратора не нужны. |
getSpace { space_id } | Пространство: название, описание, число участников и групп |
getSpaceMembers { space_id, query? } | Участники пространства (только пространство, в котором бот состоит) |
getSpaceChats { space_id, query? } | Группы и каналы пространства, которые видит бот: где он состоит и открытые. Закрытые группы без бота не показываются |
События (Update)
Каждое событие — объект с update_id и одним из полей ниже.
message — новое сообщение
{ "update_id": 1041, "message": {
"message_id": "f5df…",
"chat": { "id": "7eb7…", "type": "private" },
"from": { "id": "c91e…", "is_bot": false, "first_name": "Анна", "last_name": "Иванова", "username": "anna", "language_code": "ru" },
"text": "/help",
"entities": [{ "type": "bot_command", "offset": 0, "length": 5 }],
"date": 1758794460
} }
Команды, обычный текст и нажатия кнопок reply-клавиатуры — всё приходит как message. В группе у chat тип group и есть title.
Контекст сообщения: на что ответили и под каким постом
Чтобы бот понимал «что это?» или «у кого они его заказали?», вместе с сообщением приходит то, к чему оно относится:
| Поле | Когда есть | Что внутри |
|---|---|---|
reply_to_message | пользователь ответил (reply) на сообщение | текст этого сообщения: { id, chat, text?, entities?, attachment_count?, from_bot, created_at } |
comment_to_message | сообщение написано в обсуждении поста | текст поста в том же виде, chat.type: "channel" |
- Событие приходит боту только если обращение адресовано ему (если не включено «Видит всю переписку группы»): упоминание
@username_бота, команда или ответ на сообщение бота. Ответ на сообщение другого человека без упоминания бота событием не становится. - Пользователь может ответить на любое сообщение, в том числе чужой комментарий, и упомянуть бота («
@бот, что скажешь?»): бот получит и этот текст, и вreply_to_message— текст сообщения, на которое ответили. from_botравенtrue, если ответили на сообщение самого бота, иначеfalse.- Автор не передаётся. В
reply_to_messageиcomment_to_messageнетfrom, имени, ника иidавтора: только текст. Исключение — ответ на сообщение самого бота (тамfrom— сам бот). - Ответить можно только на сообщение из того же чата: ссылка на сообщение из другого чата игнорируется.
comment_to_messageприходит, только если бот состоит в самом канале; если пост удалён или бот не участник канала, поля нет.- Вложения не передаются: бот видит подпись и
attachment_count. Если сообщение удалено или не читается, поле просто отсутствует, событие не теряется.
{ "update_id": 1042, "message": {
"message_id": "c3d1…",
"chat": { "id": "9b02…", "type": "group", "comments_for": { "chat_id": "44ab…", "message_id": "26a1…" } },
"text": "@mill_vvbot подскажи, у кого они его заказали?",
"reply_to_message": { "message_id": "7f10…", "text": "Первый Gripen E бразильской сборки совершил полёт", "from_bot": false },
"comment_to_message": { "message_id": "26a1…", "text": "Первый Gripen E бразильской сборки…", "from_bot": false }
} }
callback_query — нажата inline-кнопка
{ "update_id": 1042, "callback_query": {
"id": "0c6a…",
"from": { "id": "c91e…", "is_bot": false, "first_name": "Анна", "last_name": "Иванова", "username": "anna", "language_code": "ru" },
"message": { "message_id": "4f71…", "chat": { "id": "7eb7…", "type": "private" } },
"data": "menu"
} }
Ответьте на него answerCallbackQuery, иначе у кнопки будет крутиться индикатор.
Другие события
chat_access— человек ответил на запросreadUserChat:grantedилиdenied.my_chat_member— бота добавили в группу или канал либо удалили оттуда.channel_post— новый пост в канале, где бот администратор.bot_started— пользователь впервые нажал «Начать». Сразу после него придётmessageс/start, так что обычно достаточно обрабатывать только его.
Мини-приложения
Мини-приложение — это ваша веб-страница, которая открывается прямо в VVelcom, без перехода в браузер: магазин, запись к врачу, анкета, игра. Страница знает, кто её открыл, умеет показывать кнопки внизу окна, вибрацию, всплывающие окна и подстраивается под тему приложения. Живой пример — приложение @VVbotMother (кнопка «Открыть» в чате с ней).
Как открыть
- Главное приложение — кнопка «Открыть» в профиле бота и в списке чатов, а также ссылка
https://uvvel.com/@username_бота?startapp=параметр. Задаётся в @VVbotMother командой/setmainapp. - Кнопка меню слева от поля ввода —
setChatMenuButtonили/setmenubutton. - Inline-кнопка
web_appпод сообщением. - Кнопка reply-клавиатуры
web_app— из такого окна можно вернуть данные боту черезsendData.
Параметр запуска для раундов и уровней. Приложение получает start_param в подписанном initData. Его можно передать ссылкой ?startapp=… или прямо в кнопке:
{ "text": "Играть: средний, 5 минут", "web_app": { "url": "https://…", "start_param": "sudoku_medium_300" } }.
Параметр берётся из копии кнопки на платформе, игрок не может его подменить. До 512 символов: латиница, цифры, _ и -.
Минимальная страница
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://apibots.vvelcom.online/bot-platform/js/vvelcom-web-app.js"></script>
</head>
<body style="background: var(--tg-theme-bg-color); color: var(--tg-theme-text-color)">
<h1 id="hello"></h1>
<script>
const app = window.VVelcom.WebApp; // он же window.Telegram.WebApp
app.ready();
document.getElementById('hello').textContent =
'Привет! Ваш id для этого бота: ' + app.initDataUnsafe.user?.id;
app.MainButton.setText('Оформить заказ').show().onClick(() => {
app.HapticFeedback.notificationOccurred('success');
app.showAlert('Заказ оформлен!');
});
</script>
</body>
</html>
Официальный telegram-web-app.js тоже работает — протокол тот же.
Что умеет страница
| Возможность | Как |
|---|---|
| Кто открыл и откуда | initData, initDataUnsafe.user, start_param |
| Кнопки внизу окна | MainButton, SecondaryButton |
| «Назад» вместо «Закрыть» | BackButton |
| Всплывающие окна | showPopup, showAlert, showConfirm |
| Вибрация | HapticFeedback |
| Цвета и тема | themeParams, CSS-переменные --tg-theme-*, setHeaderColor |
| Размер окна | expand(), requestFullscreen(), viewportHeight |
| Хранилище | CloudStorage — до 1024 ключей на пользователя |
| Вернуть данные боту | sendData() или answerWebAppQuery с вашего сервера |
| Закрыть окно | close() |
Проверка пользователя на сервере
initDataUnsafe удобно показывать, но доверять ему нельзя. Отправляйте на свой сервер
initData и проверяйте подпись — алгоритм тот же, что у Telegram, ключ выводится из токена вашего бота:
import crypto from 'node:crypto';
function checkInitData(initData, botToken, maxAgeSeconds = 86400) {
const params = new URLSearchParams(initData);
const hash = params.get('hash');
params.delete('hash');
const dataCheckString = [...params].sort(([a], [b]) => (a < b ? -1 : 1))
.map(([k, v]) => `${k}=${v}`).join('\n');
const secret = crypto.createHmac('sha256', 'WebAppData').update(botToken).digest();
const expected = crypto.createHmac('sha256', secret).update(dataCheckString).digest('hex');
if (expected !== hash) return null;
if (Date.now() / 1000 - Number(params.get('auth_date')) > maxAgeSeconds) return null;
return JSON.parse(params.get('user')); // { id, first_name, last_name, username, language_code, allows_write_to_pm }
}
Готовые библиотеки проверки initData для Telegram тоже подходят.
Примеры использования
В репозитории подготовлен каталог bot-examples: каждый пример — отдельный
небольшой проект с README, шаблоном .env.example без секретов и командами запуска.
Эхо-бот
Минимальный бот на Python и JavaScript: получение токена, getUpdates и первый ответ через sendMessage.
ИИ-бот
Подключите подходящую AI-модель или облачную платформу, добавьте свои данные, базу знаний и инструменты — от простого помощника до полноценного агента.
Telegram → VVelcom
Кросспостинг текстовых публикаций из Telegram-канала в канал VVelcom с проверкой исходного и целевого каналов.
Переезд с Telegram
- Создайте бота в @VVbotMotherUsername должен заканчиваться на
vvbot. Команды, описание и мини-приложение настраиваются так же, как у BotFather. - Поменяйте адрес APIВ библиотеке укажите сервер
https://apibots.vvelcom.onlineи новый токен. - Проверьте сценарииЗапустите бота и проверьте команды, кнопки и обработку событий. Неподдерживаемые методы Telegram нужно заменить возможностями из этой документации.
// grammY
new Bot(TOKEN, { client: { apiRoot: 'https://apibots.vvelcom.online' } });
// node-telegram-bot-api
new TelegramBot(TOKEN, { polling: true, baseApiUrl: 'https://apibots.vvelcom.online' });
// Telegraf
new Telegraf(TOKEN, { telegram: { apiRoot: 'https://apibots.vvelcom.online' } });
# aiogram 3
session = AiohttpSession(api=TelegramAPIServer.from_base("https://apibots.vvelcom.online"))
bot = Bot(TOKEN, session=session)
# python-telegram-bot
app = Application.builder().token(TOKEN).base_url("https://apibots.vvelcom.online/bot").build()
Что работает так же
- методы из этой страницы и их параметры;
- объекты
Update,Message,User,Chat,CallbackQuery; getUpdatesи webhook с заголовкомX-Telegram-Bot-Api-Secret-Token;- кнопки
callback_data,url,web_app, reply-клавиатура; - мини-приложения:
telegram-web-app.js,initDataи её проверка.
Чем отличается
- Все id (
chat.id,from.id,message_id) — строки, а не числа. Большинство библиотек это не замечают; если вы храните id в базе как число — поменяйте тип на строку.update_id— число, как в Telegram. - Из медиа бот отправляет только фото и видео (
sendPhoto,sendVideo: без кнопок и альбомов); получать файлы и отправлять документы, аудио и голосовые пока нельзя. Нет inline-режима и платежей.parse_modeпринимается, но текст показывается без разметки. answerWebAppQueryотправляет сообщение от имени бота.
Команды @VVbotMother
Всё это можно делать и в приложении @VVbotMother — кнопка «Открыть» в чате с ней. Команда без имени бота
спросит, какого бота настроить; можно указать сразу: /setname @weather_vvbot.
| Команда | Что делает |
|---|---|
/newbot | Создать бота и получить токен |
/mybots | Ваши боты и их настройки |
/setname | Имя бота |
/setdescription | «Что умеет этот бот?» — текст в пустом чате перед «Начать» |
/setabouttext | «О боте» — короткий текст в профиле |
/setuserpic | Фото бота |
/setcommands | Команды для кнопки «Меню» |
/token · /revoke | Показать токен · выпустить новый (старый сразу перестаёт работать) |
/myapps · /newapp · /listapps · /deleteapp | Мини-приложения ботов |
/setmenubutton · /setmainapp | Кнопка меню и главное мини-приложение |
/deletebot | Удалить бота |
/cancel | Отменить текущее действие |