Xiro Bot API v1.0
Xiro Bot API — Overview v1.0 · macOS
HTTP Bot API · Xirogram

Bot API для
Xirogram

Совместимый с Telegram HTTP Bot API шлюз, встроенный в MTProto-сервер. Те же токены, те же объекты, те же библиотеки — плюс ephemeral-сообщения и rich-текст.

46методов
1файловый маршрут
3типа обновлений
25 MiBна загрузку
BASE https://xiroapi.duckdns.org/bot<TOKEN>

Ничего не найдено. Попробуйте send, webhook или chat_id.

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

Шлюз слушает порт 8081 и проксируется Caddy на публичный домен. Токен бота выдаётся BotFather внутри Xirogram — он же используется в MTProto-клиенте.

1. Получите токен

Создайте бота через @BotFather в любом клиенте Xirogram. Токен выглядит как 1780243229:qqko6e….

2. Проверьте

Вызовите getMe. Ответ {"ok":true} означает, что токен и шлюз в порядке.

3. Подключите библиотеку

Укажите base URL шлюза — дальше код бота не отличается от обычного Telegram.

bash
curl -s "https://xiroapi.duckdns.org/bot<TOKEN>/getMe"

Подключение библиотек

python · python-telegram-bot
from telegram.ext import ApplicationBuilder

app = (
    ApplicationBuilder()
    .token("<TOKEN>")
    .base_url("https://xiroapi.duckdns.org/bot")
    .base_file_url("https://xiroapi.duckdns.org/file/bot")
    .build()
)
app.run_polling()
python · aiogram 3
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}, токен и шлюз в порядке.

bash
curl -s "https://xiroapi.duckdns.org/bot<TOKEN>/getMe"
3

Выбери транспорт

Шлюз поддерживает оба способа. Не включай их одновременно: во время getUpdates вызов setWebhook вернёт 409 CONFLICT.

Проще для локальной разработки: бот сам опрашивает getUpdates с таймаутом до 50 секунд.

python · requests
import requests, time

BASE = "https://xiroapi.duckdns.org"
TOKEN = "<TOKEN>"
offset = 0

while True:
    r = requests.get(
        f"{BASE}/bot{TOKEN}/getUpdates",
        params={"offset": offset, "timeout": 25},
        timeout=30,
    )
    for upd in r.json().get("result", []):
        offset = upd["update_id"] + 1
        msg = upd.get("message")
        if msg:
            requests.post(f"{BASE}/bot{TOKEN}/sendMessage", json={
                "chat_id": msg["chat"]["id"],
                "text": "Привет из Xirogram!",
            })
    time.sleep(0.2)

Для продакшена: Telegram POST-ит обновления на твой HTTPS-эндпоинт. Домен и валидный сертификат обязательны.

bash
curl -s -X POST "https://xiroapi.duckdns.org/bot<TOKEN>/setWebhook" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://bot.example.com/hook"}'

Шлюз присылает только message, edited_message и callback_query. Проверить состояние можно через getWebhookInfo, снять — через deleteWebhook.

4

Подключи библиотеку

Официальные SDK работают без форка — достаточно заменить base URL. Ниже минимальные примеры.

python · python-telegram-bot
from telegram.ext import ApplicationBuilder

app = (
    ApplicationBuilder()
    .token("<TOKEN>")
    .base_url("https://xiroapi.duckdns.org/bot")
    .base_file_url("https://xiroapi.duckdns.org/file/bot")
    .build()
)
app.run_polling()
python · aiogram 3
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.

bash · sendMessage
curl -s -X POST "https://xiroapi.duckdns.org/bot<TOKEN>/sendMessage" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": 123456789,
    "text": "Выбери действие",
    "reply_markup": {
      "inline_keyboard": [[
        {"text": "Сайт", "url": "https://example.com"},
        {"text": "Поздороваться", "callback_data": "hi"}
      ]]
    }
  }'
bash · answerCallbackQuery
curl -s -X POST "https://xiroapi.duckdns.org/bot<TOKEN>/answerCallbackQuery" \
  -H "Content-Type: application/json" \
  -d '{"callback_query_id":"<ID>","text":"Привет!"}'

Webhook на FastAPI

Минимальный сервер, который принимает обновления и отвечает эхом.

python · FastAPI
from fastapi import FastAPI, Request
import requests

app = FastAPI()
BASE = "https://xiroapi.duckdns.org"
TOKEN = "<TOKEN>"

@app.post("/hook")
async def hook(req: Request):
    upd = await req.json()
    msg = upd.get("message")
    if msg:
        requests.post(f"{BASE}/bot{TOKEN}/sendMessage", json={
            "chat_id": msg["chat"]["id"],
            "text": "echo: " + msg.get("text", ""),
        })
    return {"ok": True}

Запусти uvicorn main:app --host 0.0.0.0 --port 9000 и укажи в setWebhook публичный HTTPS-URL.

Файлы

Загрузка через multipart/form-data; лимит — 25 MiB.

bash · sendDocument
curl -s -X POST "https://xiroapi.duckdns.org/bot<TOKEN>/sendDocument" \
  -F chat_id=123456789 \
  -F document=@report.pdf

Скачивание: https://xiroapi.duckdns.org/file/bot<TOKEN>/<file_path>. Больше 25 MiB — FILE_TOO_BIG.

Меню команд

Зарегистрируй команды, чтобы клиент показывал подсказки.

bash · setMyCommands
curl -s -X POST "https://xiroapi.duckdns.org/bot<TOKEN>/setMyCommands" \
  -H "Content-Type: application/json" \
  -d '{
    "commands": [
      {"command":"start","description":"Запустить бота"},
      {"command":"help","description":"Помощь"}
    ]
  }'

Частые ошибки на старте

ОшибкаПричинаЧто делать
401 ACCESS_TOKEN_INVALIDТокен неверный или перевыпущенСкопируй токен у BotFather заново
404 METHOD_NOT_FOUNDМетод не реализован в шлюзеСверься со справочником
409 CONFLICTОдновременно polling и webhookОставь один транспорт; сними 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)
Content-Typeapplication/json, multipart/form-data, application/x-www-form-urlencoded

<METHOD> сопоставляется без учёта регистра. Диспетчер доступен и по GET, и по POST, поэтому urlencoded-запросы методом GET работают.

Аутентификация

Токен в пути — это пара <bot_id>:<secret>. Секрет сверяется со значением, сохранённым для бота. Всё остальное даёт 401 с ACCESS_TOKEN_INVALID. Отдельного auth-заголовка нет: токен в URL и есть credential, ровно как на официальном шлюзе.

Токен = полный доступ к боту. Он попадает в URL, а значит в логи прокси и в историю браузера. Не публикуйте его и не передавайте в клиентский JS.

Скачивание файлов (/file/bot…) аутентифицируется так же.

Формат запросов и ответов

успех
{
  "ok": true,
  "result": {}
}
ошибка
{
  "ok": false,
  "error_code": 400,
  "description": "CHAT_ID_INVALID"
}

error_code — это HTTP-статус. description — маркер ошибки в верхнем регистре (SCREAMING_SNAKE), не обязательно в официальных формулировках Telegram: сопоставляйте по маркеру, а не по всей строке.

Разбор полей универсальный: JSON-тело «расплющивается» в строки, нестроковые значения перемаршируются в свой JSON, а в multipart берётся первое значение каждого поля. Поэтому часть методов принимает и сокращение message_text, и полный объект InputTextMessageContent, а setChatMenuButton — и вложенный menu_button, и «плоское» тело с type на верхнем уровне.

Ошибки

Маркеры, которые шлюз может вернуть напрямую. Полный список — ниже.

МаркерHTTPКомментарий

Обновления

Шлюз порождает только три вида обновлений:

allowed_updatesКлюч обновления
messagemessage
edited_messageedited_message
callback_querycallback_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.

Разметка и entities

reply_markup принимает ровно один конструктор:

КонструкторКомментарий
inline_keyboardРяды кнопок.
keyboardresize_keyboard, one_time_keyboard, is_persistent, input_field_placeholder, selective.
remove_keyboardremove_keyboard: true, selective.
force_replyforce_reply: true, input_field_placeholder, selective.

Кнопки inline-клавиатуры

Ровно одно действие на кнопку, иначе 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.

Message entities

bold, italic, underline, strikethrough, code, pre (language), text_link (url), text_mention (user.id), spoiler, blockquote, expandable_blockquote, custom_emoji (custom_emoji_id), mention, hashtag, cashtag, bot_command, url, email, phone_number, bank_card_number, date_time (unix_time + date_time_format).

Лимиты: 256 entity на сообщение (ENTITIES_TOO_LONG), смещения в кодовых единицах UTF-16, неизвестные типы — ENTITY_TYPE_UNSUPPORTED.

Лимиты

ЛимитЗначение

Не реализовано

Все остальные официальные методы возвращают HTTP 404 METHOD_NOT_FOUND. Чаще всего до них доходят:

  • Правка: editMessageMedia, editMessageLiveLocation, stopMessageLiveLocation, stopPoll, а также inline_message_id для editMessageCaption / editMessageReplyMarkup.
  • Медиагруппы: sendMediaGroup, sendPoll, sendDice, sendGame.
  • Администрирование чатов: banChatMember, promoteChatMember, setChatPermissions, pinChatMessage, setChatTitle, leaveChat и смежные.
  • Запросы: getChat, getChatAdministrators, getChatMember, getForumTopic*.
  • Сообщения: forwardMessage, copyMessage, copyMessages.
  • Администрирование бота: setMyName, setMyDescription, close, logOut.
  • Реакции, игры и методы business-аккаунтов.

MTProto-клиенты это не затрагивает: всё, что реализовано для официальных клиентов Android/iOS/Desktop, доступно по MTProto, а не по HTTP.

Машинно-читаемые форматы

Та же спецификация, что и на этой странице, — для генерации клиентов, импорта в Postman и проверки в CI.

Состояние шлюза

ЧтоЗначение
Публичный адресhttps://xiroapi.duckdns.org
Слушатель0.0.0.0:8081 (telesrv xiro.service)
ПроксиCaddy → 127.0.0.1:8081, маршруты /bot* и /file*
Хранилище очередиPostgreSQL 17 + Redis 7 (docker gramsrv-main)
Последняя проверка1 ноября 2026 · 46/46 методов