Совместимый с Telegram HTTP Bot API шлюз, встроенный в MTProto-сервер.
Те же токены, те же объекты, те же библиотеки — плюс ephemeral-сообщения и rich-текст.
from aiogram import Bot
from aiogram.client.telegram import TelegramAPIServer
bot = Bot(
token="<TOKEN>",
server=TelegramAPIServer.from_base("https://xiroapi.duckdns.org"),
)
javascript · grammY
import { Bot } from "grammy";
const bot = new Bot("<TOKEN>", {
client: { apiRoot: "https://xiroapi.duckdns.org" },
});
bot.command("start", (ctx) => ctx.reply("Привет из Xirogram"));
bot.start();
Проверено вживую. Все 46 методов вызваны на этом сервере 1 ноября 2026: чтение отвечает 200, запись возвращает валидацию параметров (CHAT_ID_INVALID, FILE_ID_INVALID и т. п.), неизвестный метод — 404 METHOD_NOT_FOUND.
Туториал: бот за 10 минут
От @BotFather до первого ответа. Все шаги выполняются внутри Xirogram; официальные библиотеки Telegram подключаются через base URL шлюза.
1
Создай бота
Открой @BotFather в любом клиенте Xirogram, отправь /newbot, задай имя и username (должен оканчиваться на bot). В ответ придёт токен вида 1780243229:qqko6e….
Токен — это пароль бота. Не публикуй его, не коммить в git и не вставляй в клиентский JS. При утечке перевыпусти токен через /revoke у BotFather.
2
Проверь токен
Самый быстрый self-test — getMe. Если ответ {"ok":true}, токен и шлюз в порядке.
from aiogram import Bot
from aiogram.client.telegram import TelegramAPIServer
bot = Bot(
token="<TOKEN>",
server=TelegramAPIServer.from_base("https://xiroapi.duckdns.org"),
)
javascript · grammY
import { Bot } from "grammy";
const bot = new Bot("<TOKEN>", {
client: { apiRoot: "https://xiroapi.duckdns.org" },
});
bot.command("start", (ctx) => ctx.reply("Привет из Xirogram"));
bot.start();
Не все методы реализованы. Если библиотека вызывает отсутствующий метод, шлюз ответит 404 METHOD_NOT_FOUND. Сверяйся со справочником и обрабатывай эту ошибку в коде.
Рецепты
Готовые сценарии, которые можно скопировать в проект и заменить <TOKEN> и chat_id.
Inline-клавиатура и callback
Отправь кнопки, затем ответь на нажатие через answerCallbackQuery.
Оставь один транспорт; сними webhook через deleteWebhook
400 CHAT_ID_INVALID
Неверный chat_id или бот не в чате
Проверь ID и добавь бота в чат
413 FILE_TOO_BIG
Файл больше 25 MiB
Сожми файл или загрузи по URL
Чеклист перед деплоем: токен в env, webhook на HTTPS, обработка 409 и 404, логи без токена, лимит 25 MiB, команды через setMyCommands, graceful shutdown long-poll.
Транспорт
Параметр
Значение
Вызов метода
http(s)://<host>/bot<TOKEN>/<METHOD>
Скачивание файлов
http(s)://<host>/file/bot<TOKEN>/<file_path>
Настройка слушателя
TELESRV_BOT_API_ADDR; пустое значение отключает шлюз
Публичный адрес
TELESRV_BOT_API_PUBLIC_URL — его показывает BotFather
Лимит тела запроса
25 MiB файла + 1 MiB служебных данных (FILE_TOO_BIG)
<METHOD> сопоставляется без учёта регистра. Диспетчер доступен и по GET, и по POST, поэтому urlencoded-запросы методом GET работают.
Аутентификация
Токен в пути — это пара <bot_id>:<secret>. Секрет сверяется со значением, сохранённым для бота. Всё остальное даёт 401 с ACCESS_TOKEN_INVALID. Отдельного auth-заголовка нет: токен в URL и есть credential, ровно как на официальном шлюзе.
Токен = полный доступ к боту. Он попадает в URL, а значит в логи прокси и в историю браузера. Не публикуйте его и не передавайте в клиентский JS.
Скачивание файлов (/file/bot…) аутентифицируется так же.
error_code — это HTTP-статус. description — маркер ошибки в верхнем регистре (SCREAMING_SNAKE), не обязательно в официальных формулировках Telegram: сопоставляйте по маркеру, а не по всей строке.
Разбор полей универсальный: JSON-тело «расплющивается» в строки, нестроковые значения перемаршируются в свой JSON, а в multipart берётся первое значение каждого поля. Поэтому часть методов принимает и сокращение message_text, и полный объект InputTextMessageContent, а setChatMenuButton — и вложенный menu_button, и «плоское» тело с type на верхнем уровне.
Ошибки
Маркеры, которые шлюз может вернуть напрямую. Полный список — ниже.
Маркер
HTTP
Комментарий
Обновления
Шлюз порождает только три вида обновлений:
allowed_updates
Ключ обновления
message
message
edited_message
edited_message
callback_query
callback_query
allowed_updates — JSON-массив из не более 100 строк; неизвестные имена разбираются без ошибки, но не совпадают ни с чем. Не рассчитывайте на фильтрацию как на способ спрятать обновления — отбрасывайте лишние поля в боте.
Ephemeral-сообщения (Bot API 10.2) приходят как обычные message-обновления, но их message_id принадлежит ephemeral-пространству. Ответ идёт через reply_parameters.ephemeral_message_id.
Время жизни очереди задаёт TELESRV_BOT_API_UPDATE_RETENTION (по умолчанию 24h). Подтверждённые обновления удаляются раньше.
Справочник методов
46 методов и один файловый маршрут. Ниже — только то, что действительно реализовано в этой сборке; всё остальное честно отвечает 404.
Ровно одно действие на кнопку, иначе BUTTON_INVALID: url, callback_data (до 64 байт), web_app, login_url (url, bot_username, forward_text, request_write_access), switch_inline_query, switch_inline_query_current_chat, switch_inline_query_chosen_chat, copy_text. У каждой кнопки также есть text (обязателен), style (primary / danger / success / пусто) и icon_custom_emoji_id. Неизвестные поля отклоняются, а не игнорируются.
Кнопки reply-клавиатуры
Обычная строка либо объект с text и одним из: request_contact, request_location, request_poll, request_users, request_chat, web_app.
Лимиты: 256 entity на сообщение (ENTITIES_TOO_LONG), смещения в кодовых единицах UTF-16, неизвестные типы — ENTITY_TYPE_UNSUPPORTED.
Лимиты
Лимит
Значение
Не реализовано
Все остальные официальные методы возвращают HTTP 404 METHOD_NOT_FOUND. Чаще всего до них доходят:
Правка:editMessageMedia, editMessageLiveLocation, stopMessageLiveLocation, stopPoll, а также inline_message_id для editMessageCaption / editMessageReplyMarkup.