Полный Bot API для ShapitoGram. Совместим с Telegram Bot API — те же методы, поля и ответы. Меняете только адрес сервера.
curl "https://api.shapitogram.xyz/bot$BOT/getMe"
{
"ok": true,
"result": {
"id": 8123456789,
"is_bot": true,
"username": "my_bot"
}
}
50 базовых в ядре сервера + 56 расширенных через botproxy (чаты, права, опросы, топики).
Оба режима получения апдейтов, с той же семантикой offset и secret_token.
Загрузка через multipart/form-data, выдача через /file/bot<token>/….
Счета в XTR, возвраты, каталог подарков и отправка подарков от имени бота.
Бот создаётся внутри мессенджера — через @BotFather, как в Telegram. Токен выдаёт он же.
/newbot — укажите отображаемое имя, затем username, оканчивающийся на bot./token и выберите бота — BotFather пришлёт токен.Формат токена — <id бота>:<секрет>:
8123456789:AAF3kQ9xLm2vT7pR4sN8yB1cD6eF0gH5jK
/revoke
в BotFather отзывает старый и выдаёт новый; все запущенные копии бота после этого получат
401 ACCESS_TOKEN_INVALID.
| Команда | Что делает |
|---|---|
/newbot | Создать бота |
/mybots | Список ваших ботов |
/token | Показать токен |
/revoke | Отозвать токен и выдать новый |
/setname | Имя бота |
/setdescription | Описание (экран «что умеет бот») |
/setabouttext | Короткое «о боте» |
/setcommands | Список команд в меню |
/deletebot | Удалить бота |
/setinline | Включить inline-режим |
/setinlinegeo | Запрос геолокации в inline |
/setjoingroups | Можно ли добавлять в группы |
/setprivacy | Privacy mode в группах |
/setlogin | Telegram Login для бота |
/setuserpic в BotFather пока помечен как недоступный на этом сервере.
<TOKEN> подставляется целиком, вместе с двоеточием:
/bot8123456789:AAF3…/sendMessage. Регистр в имени метода не важен —
sendMessage и sendmessage равнозначны.
api.shapitogram.xyz — основной, его и указывайте в коде.
Тот же API по-прежнему отвечает и по старому адресу
https://shapitogram.xyz/bot<TOKEN>/<method>: оба хоста
ведут на один и тот же сервер, разницы в поведении нет.
export BOT="8123456789:AAF3kQ9xLm2vT7pR4sN8yB1cD6eF0gH5jK"
export API="https://api.shapitogram.xyz"
# кто я
curl "$API/bot$BOT/getMe"
# отправить сообщение
curl -X POST "$API/bot$BOT/sendMessage" \
-H "Content-Type: application/json" \
-d '{"chat_id": 123456789, "text": "Привет из Bot API"}'
import requests
BASE = "https://api.shapitogram.xyz"
TOKEN = "8123456789:AAF3kQ9xLm2vT7pR4sN8yB1cD6eF0gH5jK"
def call(method, **params):
r = requests.post(f"{BASE}/bot{TOKEN}/{method}", json=params, timeout=30)
data = r.json()
if not data.get("ok"):
raise RuntimeError(f'{data["error_code"]}: {data["description"]}')
return data["result"]
print(call("getMe"))
call("sendMessage", chat_id=123456789, text="Привет из Python")
from aiogram import Bot
from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.client.telegram import TelegramAPIServer
session = AiohttpSession(
api=TelegramAPIServer.from_base("https://api.shapitogram.xyz")
)
bot = Bot(token="8123456789:AAF3…", session=session)
from telegram.ext import ApplicationBuilder
app = (
ApplicationBuilder()
.token("8123456789:AAF3…")
.base_url("https://api.shapitogram.xyz/bot")
.build()
)
const BASE = "https://api.shapitogram.xyz";
const TOKEN = "8123456789:AAF3kQ9xLm2vT7pR4sN8yB1cD6eF0gH5jK";
async function call(method, params = {}) {
const res = await fetch(`${BASE}/bot${TOKEN}/${method}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(params),
});
const data = await res.json();
if (!data.ok) throw new Error(`${data.error_code}: ${data.description}`);
return data.result;
}
console.log(await call("getMe"));
await call("sendMessage", { chat_id: 123456789, text: "Привет из Node" });
Параметры можно передавать четырьмя способами — все поддерживаются:
| Способ | Как |
|---|---|
| Query string | GET /bot<t>/sendMessage?chat_id=1&text=hi |
| JSON | POST с Content-Type: application/json |
| Form | POST с application/x-www-form-urlencoded |
| Multipart | POST с multipart/form-data — нужен для загрузки файлов |
Успешный ответ всегда обёрнут в ok:
{
"ok": true,
"result": {
"message_id": 42,
"date": 1793025464,
"chat": { "id": 123456789, "type": "private", "first_name": "Иван" },
"text": "Привет из Bot API"
}
}
Ошибка — тоже JSON, с HTTP-кодом из error_code:
{
"ok": false,
"error_code": 401,
"description": "ACCESS_TOKEN_INVALID"
}
| Код | description | Когда |
|---|---|---|
| 401 | ACCESS_TOKEN_INVALID | Токен неверный, отозван или бот удалён |
| 404 | METHOD_NOT_FOUND | Такого метода нет (или путь не разобран) |
| 400 | CHAT_ID_INVALID | chat_id не число или равен 0 |
| 400 | MESSAGE_EMPTY | Пустой text там, где он обязателен |
| 400 | MESSAGE_TOO_LONG | Текст длиннее лимита |
| 400 | ENTITY_INVALID | Битая разметка или entities |
| 400 | BUTTON_TYPE_INVALID | В ephemeral нельзя reply-клавиатуру |
| 400 | SECRET_TOKEN_INVALID | secret_token не по формату |
| 400 | CERTIFICATE_PINNING_UNSUPPORTED | Передан certificate |
| 400 | IP_ADDRESS_UNSUPPORTED | Передан ip_address |
| 409 | CONFLICT | Параллельный getUpdates или активный webhook |
| 501 | METHOD_NOT_FOUND | Метод есть в списке, но не поддержан (напр. answerShippingQuery) |
limit ≤ 100, timeout ≤ 50 с, offset ≥ −10000getUpdates, иначе 409max_connections 1…100, по умолчанию 40Параметр parse_mode принимает три значения:
| Значение | Синтаксис |
|---|---|
HTML | <b>, <i>, <u>, <s>, <code>, <pre>, <a href>, <tg-spoiler>, <blockquote> |
Markdown | *жирный*, _курсив_, `код`, [текст](url) |
MarkdownV2 | то же, но с обязательным экранированием спецсимволов |
Альтернатива — передать готовые entities (массив объектов MessageEntity) и не
указывать parse_mode. Для подписей к медиа поля называются caption,
parse_mode, caption_entities.
Long polling. Сервер держит соединение до timeout секунд и возвращает массив апдейтов.
| Параметр | Тип | Описание |
|---|---|---|
offset | int | ID последнего обработанного апдейта + 1. Подтверждает всё, что меньше |
limit | int | 1…100, по умолчанию 100 |
timeout | int | Секунды ожидания, ≤ 50. 0 — сразу вернуть |
allowed_updates | string[] | Какие типы апдейтов получать |
curl "$API/bot$BOT/getUpdates?offset=0&limit=100&timeout=30"
getUpdates вернёт 409 CONFLICT. Сначала
deleteWebhook.
Сервер сам присылает апдейты POST-запросом на ваш HTTPS-адрес.
| Параметр | Тип | Описание |
|---|---|---|
url | string | HTTPS-адрес. Пустая строка — снять webhook |
secret_token | string | [A-Za-z0-9_-], 1…256 символов |
max_connections | int | 1…100, по умолчанию 40 |
allowed_updates | string[] | Фильтр типов |
drop_pending_updates | bool | Выбросить накопленную очередь |
curl -X POST "$API/bot$BOT/setWebhook" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hook",
"secret_token": "my-super-secret",
"max_connections": 40,
"allowed_updates": ["message", "callback_query"]
}'
Если задан secret_token, каждый запрос несёт заголовок
X-Telegram-Bot-Api-Secret-Token — сравнивайте его с ожидаемым значением.
certificate и ip_address не поддерживаются: сервер отвечает
CERTIFICATE_PINNING_UNSUPPORTED / IP_ADDRESS_UNSUPPORTED.
Используйте обычный валидный сертификат.
В allowed_updates можно перечислять:
message · edited_message · channel_post · edited_channel_post · callback_query · inline_query · chosen_inline_result · pre_checkout_query · shipping_query · poll · poll_answer · my_chat_member · chat_member · chat_join_request · message_reaction · business_connection · business_message
| Метод | Описание | Параметры |
|---|---|---|
getMecore | Информация о боте: id, имя, username, флаги | — |
setMyCommandscore | Установить список команд | commands, scope, language_code |
getMyCommandscore | Получить список команд | scope, language_code |
deleteMyCommandscore | Очистить команды | scope, language_code |
setMyNameext | Сменить имя бота | name |
getMyNameext | Текущее имя | — |
setMyDescriptionext | Описание бота | description |
getMyDescriptionext | Текущее описание | — |
setMyShortDescriptionext | Короткое «о боте» | short_description |
getMyShortDescriptionext | Текущее короткое описание | — |
logOutext | Завершить сессию бота на сервере | — |
closeext | Закрыть инстанс бота | — |
| Метод | Описание | Параметры |
|---|---|---|
sendMessagecore | Отправить текст | chat_id, text, parse_mode, entities, reply_markup, reply_to_message_id, disable_web_page_preview, disable_notification |
sendRichMessagecore | Rich-сообщение (блоки: текст, медиа, списки) | chat_id, rich_message, reply_markup, reply_to_message_id, protect_content, message_effect_id |
editMessageTextcore | Изменить текст отправленного | chat_id, message_id, text, parse_mode, entities, reply_markup |
editMessageCaptionext | Изменить подпись к медиа | chat_id, message_id, caption, parse_mode, reply_markup |
editMessageMediaext | Заменить медиа в сообщении | chat_id, message_id, media, reply_markup |
editMessageReplyMarkupext | Заменить клавиатуру | chat_id, message_id, reply_markup |
deleteMessagecore | Удалить одно сообщение | chat_id, message_id |
deleteMessagesext | Удалить пачкой | chat_id, message_ids |
forwardMessageext | Переслать сообщение | chat_id, from_chat_id, message_id |
forwardMessagesext | Переслать несколько | chat_id, from_chat_id, message_ids |
copyMessageext | Копия без пометки «переслано» | chat_id, from_chat_id, message_id |
copyMessagesext | Копировать пачкой | chat_id, from_chat_id, message_ids |
sendChatActionext | «печатает», «загружает фото» и т.п. | chat_id, action |
curl -X POST "$API/bot$BOT/sendMessage" \
-H "Content-Type: application/json" \
-d '{
"chat_id": 123456789,
"text": "Выберите действие",
"parse_mode": "HTML",
"reply_markup": {
"inline_keyboard": [
[
{"text": "Открыть сайт", "url": "https://shapitogram.xyz"},
{"text": "Поздороваться", "callback_data": "hello"}
]
]
}
}'
| Метод | Описание | Параметры |
|---|---|---|
sendPhotocore | Фото | chat_id, photo, caption, parse_mode, caption_entities, reply_markup, reply_to_message_id |
sendVideocore | Видео | chat_id, video, caption, … |
sendAnimationcore | GIF / анимация | chat_id, animation, caption, … |
sendAudiocore | Аудиофайл | chat_id, audio, caption, … |
sendDocumentcore | Документ | chat_id, document, caption, … |
sendStickercore | Стикер | chat_id, sticker, reply_markup |
sendVoicecore | Голосовое | chat_id, voice, caption, … |
sendVideoNotecore | Кружок | chat_id, video_note |
sendLivePhotocore | Live Photo | chat_id, live_photo, photo |
sendMediaGroupext | Альбом (2–10 элементов) | chat_id, media[] |
sendContactcore | Контакт | chat_id, phone_number, first_name, last_name, vcard |
sendLocationcore | Геолокация | chat_id, latitude, longitude, horizontal_accuracy, live_period |
sendVenuecore | Место на карте | chat_id, latitude, longitude, title, address |
getFilecore | Метаданные файла и file_path | file_id |
В поле медиа можно передать одно из трёх:
file_id — уже загруженный ранее файл;https://-URL — сервер скачает сам;multipart/form-data — поле называется так же, как метод (photo, video, …).curl -X POST "$API/bot$BOT/sendPhoto" \
-F "chat_id=123456789" \
-F "photo=@/path/to/picture.jpg" \
-F "caption=Подпись"
Скачать файл:
curl "$API/file/bot$BOT/<file_path>" -o file.jpg
Все методы этого раздела — расширенные (ext).
| Метод | Описание | Параметры |
|---|---|---|
getChat | Информация о чате | chat_id |
getChatMember | Участник и его статус | chat_id, user_id |
getChatAdministrators | Список админов | chat_id |
getChatMemberCount | Число участников | chat_id |
banChatMember | Забанить | chat_id, user_id, until_date |
unbanChatMember | Разбанить | chat_id, user_id |
restrictChatMember | Ограничить права | chat_id, user_id, permissions |
setChatPermissions | Права по умолчанию для всех | chat_id, permissions |
promoteChatMember | Повысить до админа | chat_id, user_id, can_* |
setChatAdministratorCustomTitle | Свой титул админа | chat_id, user_id, custom_title |
pinChatMessage | Закрепить | chat_id, message_id |
unpinChatMessage | Открепить | chat_id, message_id |
unpinAllChatMessages | Открепить всё | chat_id |
leaveChat | Выйти из чата | chat_id |
setChatTitle | Переименовать чат | chat_id, title |
setChatDescription | Описание чата | chat_id, description |
setChatPhoto | Аватар чата | chat_id, photo |
deleteChatPhoto | Убрать аватар | chat_id |
exportChatInviteLink | Постоянная ссылка-приглашение | chat_id |
createChatInviteLink | Новая ссылка | chat_id, name, expire_date, member_limit |
revokeChatInviteLink | Отозвать ссылку | chat_id, invite_link |
approveChatJoinRequest | Одобрить заявку | chat_id, user_id |
declineChatJoinRequest | Отклонить заявку | chat_id, user_id |
banChatSenderChat | Забанить канал от имени чата | chat_id, sender_chat_id |
unbanChatSenderChat | Разбанить канал | chat_id, sender_chat_id |
| Метод | Описание | Параметры |
|---|---|---|
sendPollext | Опрос или викторина | chat_id, question, options, type, is_anonymous, allows_multiple_answers, correct_option_id, explanation, open_period |
stopPollext | Остановить опрос | chat_id, message_id |
sendDiceext | Кубик / дартс / слоты | chat_id, emoji |
setMessageReactionext | Поставить реакцию | chat_id, message_id, reaction[], is_big |
getUserProfilePhotosext | Аватары пользователя | user_id, offset, limit |
| Метод | Описание | Параметры |
|---|---|---|
answerCallbackQuerycore | Ответ на нажатие кнопки (снимает «часики») | callback_query_id, text, show_alert, url, cache_time |
answerWebAppQuerycore | Результат из Mini App | web_app_query_id, result |
savePreparedInlineMessagecore | Подготовить сообщение для отправки из inline | user_id, result, allow_*_chats |
answerInlineQueryext | Ответ на inline-запрос (@bot запрос) | inline_query_id, results[], cache_time |
| Объект | Где работает | Поля |
|---|---|---|
InlineKeyboardMarkup | В любом сообщении | inline_keyboard[][] — кнопки с callback_data, url, web_app |
ReplyKeyboardMarkup | Только в приватном чате | keyboard[][], resize_keyboard, one_time_keyboard, is_persistent |
ReplyKeyboardRemove | Убрать reply-клавиатуру | remove_keyboard: true |
ForceReply | Заставить ответить | force_reply: true, input_field_placeholder |
| Метод | Описание | Параметры |
|---|---|---|
setChatMenuButtoncore | Кнопка меню (команды / Mini App) | chat_id, menu_button |
getChatMenuButtoncore | Текущая кнопка меню | chat_id |
setUserEmojiStatuscore | Emoji-статус пользователя (нужно разрешение) | user_id, emoji_status_custom_emoji_id, emoji_status_expiration_date |
Все — расширенные (ext).
| Метод | Описание | Параметры |
|---|---|---|
createForumTopic | Создать топик | chat_id, name, icon_color, icon_custom_emoji_id |
editForumTopic | Переименовать / сменить иконку | chat_id, message_thread_id, name |
closeForumTopic | Закрыть | chat_id, message_thread_id |
reopenForumTopic | Открыть заново | chat_id, message_thread_id |
deleteForumTopic | Удалить | chat_id, message_thread_id |
| Метод | Описание | Параметры |
|---|---|---|
getStickerSetext | Набор стикеров и его состав | name |
getCustomEmojiStickersext | Кастомные emoji по ID | custom_emoji_ids[] |
| Метод | Описание | Параметры |
|---|---|---|
sendInvoicecore | Счёт на оплату (валюта XTR) | chat_id, title, description, payload, currency, prices[] |
answerPreCheckoutQuerycore | Подтвердить или отклонить оплату | pre_checkout_query_id, ok, error_message |
answerShippingQuerycore | Не поддерживается — 501 | — |
refundStarPaymentcore | Вернуть Stars | user_id, telegram_payment_charge_id |
getAvailableGiftscore | Каталог подарков | — |
sendGiftcore | Подарить подарок | gift_id, user_id, star_count, text, pay_for_upgrade |
giftPremiumSubscriptioncore | Подарить Premium | user_id, month_count, star_count, text |
sendInvoice с currency: "XTR" и массивом prices.pre_checkout_query.answerPreCheckoutQuery с ok: true (или false + error_message).message с successful_payment — там telegram_payment_charge_id.refundStarPayment по этому же charge_id.Отдельный механизм этого сервера: сообщение видит только один получатель и только пока открыт экран. Используется для подсказок и «временных» ответов на кнопки.
| Метод | Описание | Параметры |
|---|---|---|
editEphemeralMessageTextcore | Изменить текст | ephemeral_message_id, text, parse_mode |
editEphemeralMessageMediacore | Заменить медиа | ephemeral_message_id, media |
editEphemeralMessageCaptioncore | Изменить подпись | ephemeral_message_id, caption |
editEphemeralMessageReplyMarkupcore | Заменить клавиатуру | ephemeral_message_id, reply_markup |
deleteEphemeralMessagecore | Удалить | ephemeral_message_id |
Отправка ephemeral-сообщения — это обычный sendMessage с
receiver_user_id (или callback_query_id) вместо обычной доставки в чат.
В таком сообщении допустима только inline-клавиатура.
Поля совпадают с Telegram Bot API. Ниже — то, что встречается чаще всего.
{
"id": 123456789,
"is_bot": false,
"first_name": "Иван",
"last_name": "",
"username": "username",
"language_code": "ru"
}
{ "id": 123456789, "type": "private", "first_name": "Иван", "username": "username" }
{ "id": -1001234567890, "type": "channel", "title": "ShapitoGram", "username": "shapitogram" }
{ "id": -1001234567890, "type": "supergroup", "title": "Чат" }
{
"message_id": 42,
"date": 1793025464,
"chat": { "id": 123456789, "type": "private" },
"from": { "id": 8123456789, "is_bot": true, "first_name": "Мой бот" },
"text": "Привет",
"reply_to_message": { "message_id": 41, "chat": { "id": 123456789 } }
}
{
"update_id": 100500,
"message": { ... }
}
В объекте приходит ровно одно поле-«полезная нагрузка»:
message, edited_message, callback_query,
inline_query, pre_checkout_query, poll и т.д.
{
"id": "4382901234",
"from": { "id": 123456789, "is_bot": false, "first_name": "Иван" },
"message": { "message_id": 42, "chat": { "id": 123456789 } },
"chat_instance": "1234567890",
"data": "hello"
}
{ "label": "Подписка на месяц", "amount": 100 }
amount — в минимальных единицах. Для XTR это просто количество звёзд.
{ "command": "start", "description": "Запустить бота" }
API намеренно совместим, но это не копия — вот что важно знать.
| Что | Как здесь |
|---|---|
| Домен | Свой, а не api.telegram.org. Библиотекам нужно явно указать базовый URL |
| Токены | Выдаёт локальный @BotFather; токены Telegram не работают |
| Платежи | Только XTR (Stars). Провайдеры вроде Stripe не подключены, provider_token не нужен |
| Доставка | Только Telegram-платежи Stars, без shipping — answerShippingQuery возвращает 501 |
| Pinning сертификата | Не поддержан: certificate и ip_address в setWebhook дают 400 |
| Расширенные методы | 56 методов (чаты, права, опросы, топики, реакции) обслуживает отдельный сервис botproxy поверх MTProto |
| Ephemeral | Дополнительный механизм, которого нет в Telegram |
| Ограничение поллинга | Один getUpdates на бота одновременно — иначе 409 |
| Хранение апдейтов | 24 часа (как в Telegram) |
api.telegram.org, укажите ей file-базу явно: /file/bot.
import asyncio
from aiogram import Bot, Dispatcher, F
from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.client.telegram import TelegramAPIServer
from aiogram.types import Message
TOKEN = "8123456789:AAF3kQ9xLm2vT7pR4sN8yB1cD6eF0gH5jK"
BASE = "https://api.shapitogram.xyz"
session = AiohttpSession(api=TelegramAPIServer.from_base(BASE))
bot = Bot(token=TOKEN, session=session)
dp = Dispatcher()
@dp.message(F.text)
async def echo(message: Message):
await message.answer(f"Ты написал: {message.text}")
async def main():
await dp.start_polling(bot)
asyncio.run(main())
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
@dp.message(F.text == "/menu")
async def menu(message: Message):
kb = InlineKeyboardMarkup(inline_keyboard=[[
InlineKeyboardButton(text="Погладить", callback_data="pat"),
InlineKeyboardButton(text="Сайт", url="https://shapitogram.xyz"),
]])
await message.answer("Что делаем?", reply_markup=kb)
@dp.callback_query(F.data == "pat")
async def pat(call: CallbackQuery):
await call.answer("Мур!", show_alert=True)
await call.message.edit_text("Погладил 🐈")
from fastapi import FastAPI, Request, Header, HTTPException
import httpx
BASE = "https://api.shapitogram.xyz"
TOKEN = "8123456789:AAF3…"
SECRET = "my-super-secret"
app = FastAPI()
@app.post("/hook")
async def hook(request: Request,
x_telegram_bot_api_secret_token: str = Header(default="")):
if x_telegram_bot_api_secret_token != SECRET:
raise HTTPException(403)
update = await request.json()
msg = update.get("message")
if msg and msg.get("text"):
await httpx.AsyncClient().post(
f"{BASE}/bot{TOKEN}/sendMessage",
json={"chat_id": msg["chat"]["id"], "text": msg["text"]},
)
return {"ok": True}
curl -X POST "$API/bot$BOT/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/hook","secret_token":"my-super-secret"}'
# проверить
curl "$API/bot$BOT/getWebhookInfo"
# снять и вернуться к getUpdates
curl -X POST "$API/bot$BOT/deleteWebhook"
Токен скопирован не целиком, либо был /revoke. Проверьте, что в строке есть двоеточие
и секрет после него, и что между /bot и токеном нет пробелов.
Либо уже установлен webhook (deleteWebhook), либо запущено два процесса с одним токеном.
Второй вариант — самая частая причина: старый инстанс бота не остановлен.
Расширенные методы (ext) обслуживает botproxy. Если он лежит, эти методы недоступны, а базовые продолжают работать. Проверьте, что сервис запущен.
botproxy логинится в сеть под ботом через MTProto и держит сессию. Первый вызов после старта может занять несколько секунд — дальше сессия переиспользуется.
file_path берётся из ответа getFile и живёт ограниченное время. Если
ссылка «протухла», вызовите getFile снова.
Нет. Это отдельная сеть со своей базой ботов. Нужен бот, созданный в @BotFather этой сети.
ShapitoGram Bot API · 106 методов · документ обновлён 26.10.2026