OnyxGram Developers
Bot API
HTTP API для создания ботов OnyxGram: сообщения пользователям, группам и каналам, получение ID, администрирование, кнопки выбора чатов, медиа, Guest Bots, платежи, подарки, бизнес-аккаунты, long polling и webhooks.
https://dev-angel-7553.dev/bot<token>/METHOD
История изменений последнее: business-account
Начало работы
Передавайте токен бота в адресе запроса. Для большинства методов используется POST с JSON.
application/json, query-параметры и multipart/form-data для загрузки файлов.
# Проверить токен
curl "https://dev-angel-7553.dev/bot<TOKEN>/getMe"
# Отправить сообщение
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendMessage" \
-H "Content-Type: application/json" \
-d '{"chat_id":123456789,"text":"Привет из OnyxGram Bot API"}'
chat_idЧисловой ID пользователя, группы, супергруппы или канала. Для публичного канала и супергруппы можно передать @username.reply_to_message_idID сообщения, на которое отвечает бот.disable_notificationОтправить сообщение без звука.reply_markupКлавиатура или набор inline-кнопок.https://dev-angel-7553.dev/bot<TOKEN>/<METHOD>.
Доступные методы
Методы сгруппированы по назначению. GET отмечен отдельно; остальные методы вызываются через POST.
Методы не найдены.
getMeДанные бота и проверка токена.getChatИнформация о чате.getIdПолучить Bot API ID пользователя, группы или канала по @username или известному ID.sendChatActionИндикатор действия в чате.sendMessageDraftПотоковый черновик сообщения в личном чате.getFileИнформация и путь к файлу.getBusinessConnectionПолучить подключение бизнес-бота.getUserProfilePhotosФотографии профиля пользователя с пагинацией.sendMessageТекст, reply и кнопки.editMessageTextИзменить текст сообщения.deleteMessageУдалить сообщение.copyMessageСкопировать сообщение.copyMessagesСкопировать несколько сообщений.forwardMessageПереслать сообщение.forwardMessagesПереслать несколько сообщений.editMessageCaptionИзменить подпись к медиа.editMessageMediaЗаменить медиа в сообщении.editMessageReplyMarkupИзменить inline-клавиатуру.deleteMessagesУдалить несколько сообщений.sendPollОтправить опрос или викторину.stopPollОстановить опрос и получить итоговые результаты.setMessageReactionПоставить или снять реакции на сообщение.sendPhotoОтправить фото.sendVideoОтправить видео.sendDocumentОтправить документ.sendAudioОтправить аудио.sendVoiceОтправить голосовое.sendAnimationОтправить анимацию.sendStickerОтправить стикер.sendDiceОтправить случайный результат кубика.sendVideoNoteОтправить видеосообщение.sendMediaGroupОтправить альбом медиа.sendContactОтправить контакт с именем и номером телефона.sendInvoiceСчет в звёздах.createInvoiceLinkСсылка на счет.answerPreCheckoutQueryПодтвердить оплату.answerCallbackQueryОтветить на callback.answerInlineQueryВернуть результаты inline-запроса.answerWebAppQueryОтправить результат Mini App.answerGuestQueryОтветить в исходном чате на гостевой запрос.getAvailableGiftsКаталог, цены и остатки подарков.sendGiftОтправить подарок пользователю.getUserGiftsПодарки пользователя.getChatGiftsПодарки канала.getBusinessAccountGiftsПодарки подключённого аккаунта.getBusinessAccountStarBalanceБаланс звёзд аккаунта.convertGiftToStarsПродать подарок за звёзды.upgradeGiftУлучшить подарок до уникального.transferGiftПередать уникальный подарок.setBusinessAccountGiftSettingsКакие подарки принимает аккаунт.transferBusinessAccountStarsВывести звёзды владельцу бота.giftPremiumSubscriptionПодарить Premium за звёзды.readBusinessMessageОтметить сообщение прочитанным от имени аккаунта.deleteBusinessMessagesУдалить сообщения в чате аккаунта.setBusinessAccountNameИмя и фамилия аккаунта.setBusinessAccountBioОписание в профиле.setBusinessAccountUsernameЮзернейм аккаунта.setMyCommandsУстановить команды.getMyCommandsПолучить команды.deleteMyCommandsУдалить команды.setMyNameИзменить имя.getMyNameПолучить имя.setMyDescriptionИзменить описание.getMyDescriptionПолучить описание.setMyShortDescriptionИзменить краткое описание.getMyShortDescriptionПолучить краткое описание.setChatMenuButtonНастроить кнопку меню бота.getChatMenuButtonПолучить кнопку меню бота.getMyDefaultAdministratorRightsПрава администратора по умолчанию при добавлении бота.setMyDefaultAdministratorRightsЗадать права администратора по умолчанию для групп или каналов.getMyStarBalanceБаланс звёзд владельца бота.getStarTransactionsИстория операций в звёздах.refundStarPaymentВернуть платёж пользователю.getChatMemberCountКоличество участников.getChatAdministratorsСписок администраторов.getChatMemberСтатус и права участника.banChatMemberЗаблокировать участника.unbanChatMemberСнять блокировку.restrictChatMemberИзменить ограничения участника.promoteChatMemberИзменить права администратора.setChatAdministratorCustomTitleЗадать должность администратора.pinChatMessageЗакрепить сообщение.unpinChatMessageОткрепить сообщение.unpinAllChatMessagesСнять все закрепления.setChatPermissionsПрава по умолчанию для всех участников.exportChatInviteLinkОсновная пригласительная ссылка бота, старая при этом отзывается.createChatInviteLinkСоздать дополнительную ссылку: срок, лимит участников или заявки.editChatInviteLinkИзменить настройки своей ссылки.revokeChatInviteLinkОтозвать ссылку.approveChatJoinRequestОдобрить заявку на вступление.declineChatJoinRequestОтклонить заявку на вступление.setChatTitleИзменить название чата.setChatDescriptionИзменить описание чата.setChatPhotoУстановить фото чата.deleteChatPhotoУдалить фото чата.leaveChatБоту покинуть группу или канал.getUpdatesLong polling до 30 секунд.setWebhookВключить HTTPS webhook.deleteWebhookОтключить webhook.getWebhookInfoСтатус и ошибки доставки.createForumTopicСоздать тему в форуме.editForumTopicИзменить название или значок темы.closeForumTopicЗакрыть тему.reopenForumTopicОткрыть тему повторно.deleteForumTopicУдалить тему и её сообщения.getThemesСписок тем оформления с палитрами и файлом .attheme.getThemeОдна тема по slug или theme_id.getChatThemesТемы чатов, которые выбираются эмодзи.getChatThemeТема, установленная в конкретном чате.setChatThemeУстановить или снять тему чата.getStickerSetПолучить набор стикеров по названию.getCustomEmojiStickersСтикеры кастомных эмодзи по их идентификаторам.uploadStickerFileЗагрузить файл для последующего использования в наборе.createNewStickerSetСоздать новый набор стикеров бота.addStickerToSetДобавить стикер в набор.deleteStickerFromSetУдалить стикер из набора.replaceStickerInSetЗаменить стикер в наборе на другой.setStickerPositionInSetИзменить позицию стикера в наборе.setStickerEmojiListЗадать список эмодзи стикера.setStickerKeywordsЗадать ключевые слова для поиска стикера.setStickerMaskPositionЗадать положение маски стикера.setStickerSetTitleИзменить название набора.setStickerSetThumbnailЗадать обложку набора по стикеру из него.setCustomEmojiStickerSetThumbnailЗадать обложку набора кастомных эмодзи.deleteStickerSetУдалить набор стикеров, созданный ботом.Получение ID
getId — расширение OnyxGram для настройки рассылок, модерации и публикации в каналы.
# Пользователь, публичная супергруппа или канал
curl "https://dev-angel-7553.dev/bot<TOKEN>/getId?username=@example"
# Нормализовать уже известный chat_id
curl "https://dev-angel-7553.dev/bot<TOKEN>/getId?chat_id=-1001234567890"
# Ответ
{"ok":true,"result":{"id":-1001234567890,"type":"channel","username":"example","title":"Example"}}
can_post_messages.
Потоковый текст
sendMessageDraft показывает пользователю частичный ответ, пока бот формирует итоговое сообщение.
# Один draft_id используется для всех частей одного ответа
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendMessageDraft" \
-H "Content-Type: application/json" \
-d '{"chat_id":123456789,"draft_id":42,"text":"Формирую ответ..."}'
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendMessageDraft" \
-H "Content-Type: application/json" \
-d '{"chat_id":123456789,"draft_id":42,"text":"Готовый текст ответа"}'
# Итог обязательно сохраняется обычным сообщением
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendMessage" \
-H "Content-Type: application/json" \
-d '{"chat_id":123456789,"text":"Готовый текст ответа"}'
chat_idОбязательный ID личного чата с пользователем.draft_idОбязательный ненулевой ID потока. Один ID связывает обновления с общей анимацией.textДо 4096 символов после разбора. Пустая строка показывает состояние ожидания.parse_mode / entitiesФорматирование текста, как в sendMessage.message_thread_idНеобязательный ID темы личного чата.sendMessage с полным ответом.
Медиа и файлы
Передавайте file_id, публичный HTTP(S)-URL или загрузите файл через multipart.
# Фото по URL
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendPhoto" \
-H "Content-Type: application/json" \
-d '{
"chat_id": 123456789,
"photo": "https://example.com/photo.jpg",
"caption": "Фото из Bot API"
}'
# Документ загрузкой multipart/form-data
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendDocument" \
-F "chat_id=123456789" \
-F "document=attach://file" \
-F "caption=Файл из Bot API" \
-F "file=@./example.pdf"
file_id и используйте его вместо повторной загрузки файла.
Кубики
sendDice создаёт сообщение с уже определённым случайным значением. Не загружайте файл: передайте chat_id и при необходимости emoji.
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendDice" \
-H "Content-Type: application/json" \
-d '{"chat_id":123456789,"emoji":"🎯","disable_notification":true}'
# Фрагмент успешного ответа
{"ok":true,"result":{"message_id":42,"dice":{"emoji":"🎯","value":4}}}
emojiНеобязательный вид игры. Поддерживаются 🎲 (по умолчанию), 🎯, 🏀, ⚽, 🎳 и 🎰. Любое другое значение вернёт 400.diceОбъект сообщения и входящего update с полями emoji и value. Диапазон значений зависит от эмодзи: 1–6 для 🎲, 🎯 и 🎳, 1–5 для 🏀 и ⚽, 1–64 для 🎰.reply_to_message_id / reply_markupПоддерживаются так же, как при отправке обычного сообщения.copyMessage и copyMessages не поддерживают dice и вернут ошибку 400. forwardMessage и forwardMessages пересылают исходный результат без нового броска.
Опросы и викторины
sendPoll отправляет обычный опрос или викторину с правильным ответом. Файл загружать не нужно: достаточно question и списка options.
# Обычный опрос
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendPoll" \
-H "Content-Type: application/json" \
-d '{
"chat_id": 123456789,
"question": "Когда созвон?",
"options": ["Сегодня", "Завтра", "На следующей неделе"],
"allows_multiple_answers": true
}'
# Викторина с правильным ответом и пояснением
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendPoll" \
-H "Content-Type: application/json" \
-d '{
"chat_id": 123456789,
"question": "Какой метод отправляет кубик?",
"options": ["sendDice", "sendGame", "sendMedia"],
"type": "quiz",
"correct_option_ids": [0],
"explanation": "sendDice возвращает готовое значение в поле dice."
}'
# Викторина, по которой бот узнаёт, кто как ответил
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendPoll" \
-H "Content-Type: application/json" \
-d '{
"chat_id": -1001234567890,
"question": "Что из этого — цвет?",
"options": [
{"text": "кошка"},
{"text": "синий"},
{"text": "семь"}
],
"type": "quiz",
"correct_option_ids": [1],
"is_anonymous": false,
"allows_revoting": false,
"open_period": 120
}'
questionТекст вопроса, от 1 до 300 символов.question_parse_modeРазметка вопроса: HTML, Markdown или MarkdownV2. Вместо неё можно передать question_entities.optionsОт 1 до 12 вариантов, каждый от 1 до 100 символов. Принимаются строки и объекты с полями text, text_parse_mode, text_entities.typeregular по умолчанию или quiz.correct_option_idsИндексы правильных вариантов с нуля. Обязателен для викторины и запрещён для обычного опроса. Старое поле correct_option_id тоже принимается.explanationПояснение к правильному ответу викторины, до 200 символов. Разметка — explanation_parse_mode или explanation_entities.allows_multiple_answersРазрешить несколько ответов. С quiz несовместимо.is_anonymousПо умолчанию true. Передайте false, чтобы голоса были видны и приходили обновления poll_answer.open_periodСколько секунд опрос открыт, от 5 до 2628000. Несовместим с close_date.close_dateМомент закрытия, unix-время. Должен отстоять от текущего на те же 5–2628000 секунд.allows_revotingПо умолчанию true. Викторина не даёт переголосовать независимо от этого поля.shuffle_optionsПоказывать варианты каждому в своём порядке.allow_adding_optionsРазрешить участникам дописывать свои варианты.hide_results_until_closesСкрыть счёт до закрытия. Требует open_period или close_date.members_onlyГолосовать могут только те, кто в чате не меньше суток.country_codesДо 12 кодов стран по ISO 3166-1 alpha-2. Голос принимается только с номера из списка.custom_emoji — остальные entities отбрасываются, как и в Bot API. В пояснении к викторине разметка сохраняется целиком. Один автор может создать не больше пяти опросов в минуту, дальше приходит 429 с retry_after.
Результаты приходят двумя обновлениями, и только тому боту, который отправил опрос. poll несёт новое состояние опроса целиком — счёт по вариантам и признак закрытия. poll_answer сообщает, кто как проголосовал, и работает лишь при is_anonymous: false: анонимный опрос не раскрывает голосующих даже автору. Пустой option_ids в poll_answer означает, что голос отозвали.
Правильные ответы викторины и пояснение сервер отдаёт только после закрытия опроса — до этого correct_option_ids и explanation в обновлениях отсутствуют.
Кнопки
Inline-кнопки поддерживают URL, callback, Mini Apps, оплату, копирование текста и переключение inline-запроса.
curl -X POST "https://dev-angel-7553.dev/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": "check"}
]]
}
}'
При нажатии callback-кнопки бот получает callback_query. После обработки вызовите answerCallbackQuery. У каждой inline-кнопки должно быть ровно одно действие.
Выбор пользователя, группы или канала
request_chat и request_users используются только в обычной ReplyKeyboardMarkup. После выбора бот получает сообщение с chat_shared или users_shared.
{
"chat_id": 123456789,
"text": "Выберите объект",
"reply_markup": {
"keyboard": [
[{"text":"Выбрать группу","request_chat":{"request_id":1,"chat_is_channel":false,"request_title":true}}],
[{"text":"Выбрать канал","request_chat":{"request_id":2,"chat_is_channel":true,"user_administrator_rights":{"can_post_messages":true},"request_username":true}}],
[{"text":"Выбрать пользователя","request_users":{"request_id":3,"max_quantity":1,"request_name":true,"request_username":true}}]
],
"resize_keyboard": true
}
}
Для запуска Mini App используйте кнопку с полем web_app и публичным HTTPS-адресом приложения:
{
"text": "Открыть приложение",
"web_app": {"url": "https://example.com/app"}
}
Приложение должно вызвать Telegram.WebApp.ready(), передать initData на backend и проверять его подпись до выполнения действий от имени пользователя. Полный порядок настройки описан в разделе Web Apps.
Inline-режим
Включите inline-режим в Mini App BotFather. После запроса @bot запрос бот получает inline_query и отвечает методом answerInlineQuery.
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/answerInlineQuery" \
-H "Content-Type: application/json" \
-d '{
"inline_query_id": "QUERY_ID",
"cache_time": 10,
"results": [{
"type": "article",
"id": "rate-gram",
"title": "Курс GRAM",
"input_message_content": {
"message_text": "GRAM = 1.25$ (112₽)"
}
}]
}'
Inline-медиа и музыка
В results можно вернуть до 50 элементов. Для каждого элемента нужен уникальный строковый id длиной до 64 байт. Поддерживаются article, photo, video, gif, mpeg4_gif, audio, voice, document, sticker, contact, location и venue.
Для медиа используйте публичный HTTPS/HTTP URL или сохранённый file_id. URL должен быть доступен серверу OnyxGram. Для photo, video, gif и mpeg4_gif при отправке по URL обязательны thumbnail_url. Для музыки используется тип audio:
{
"inline_query_id": "QUERY_ID",
"cache_time": 30,
"is_personal": true,
"results": [
{
"type": "audio",
"id": "track-42",
"audio_url": "https://cdn.example.com/music/track-42.mp3",
"title": "Рассвет",
"performer": "OnyxGram",
"audio_duration": 187,
"caption": "Трек из inline-поиска"
},
{
"type": "gif",
"id": "gif-42",
"gif_url": "https://cdn.example.com/gifs/42.mp4",
"thumbnail_url": "https://cdn.example.com/gifs/42.jpg",
"title": "Анимация"
}
]
}
Вместо URL можно передать кэшированный файл. Например, для музыки используйте audio_file_id, для GIF — gif_file_id, для MP4-анимации — mpeg4_file_id, для стикера — sticker_file_id. Это уменьшает задержку повторных inline-ответов и не требует повторной загрузки файла.
audioМузыка по audio_url или audio_file_id. При отправке по URL укажите title; можно передать performer, audio_duration и thumbnail_url.photo / videoНужны URL медиа и thumbnail_url, либо соответствующий cached file_id.gif / mpeg4_gifДля GIF используйте gif_url или gif_file_id, для MP4-анимации — mpeg4_url или mpeg4_file_id.voice / documentИспользуйте voice_url/voice_file_id или document_url/document_file_id.input_message_contentОбязательно для article; для медиа необязательно и задаёт текст сообщения после выбора результата.Пагинация и кэш
Клиент передаёт предыдущий next_offset в новом inline_query. Верните следующий offset в ответе или пустую строку, если результаты закончились. cache_time задаёт время кэширования ответа в секундах от 0 до 86400; для персональных результатов включайте is_personal: true.
{
"inline_query_id": "QUERY_ID",
"cache_time": 10,
"is_personal": true,
"next_offset": "page-2",
"results": []
}
Пустой results означает, что совпадений нет. Ответьте на каждый полученный inline_query в течение срока действия запроса; просроченный ID будет отклонён.
Управление чатами
Бот может получать участников, изменять права, назначать администраторов, управлять закреплениями, пригласительными ссылками и форумными темами.
# Ограничить отправку сообщений
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/restrictChatMember" \
-H "Content-Type: application/json" \
-d '{
"chat_id": -1800000055001,
"user_id": 123456789,
"permissions": {"can_send_messages": false}
}'
# Вернуть право писать
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/restrictChatMember" \
-H "Content-Type: application/json" \
-d '{
"chat_id": -1800000055001,
"user_id": 123456789,
"permissions": {"can_send_messages": true}
}'
banChatMember принимает любой user_id, даже если этого человека в чате никогда не было — так строится чёрный список заранее. unbanChatMember для незнакомца тоже успешен и ничего не меняет. А вот restrictChatMember отвечает ошибкой: у того, кого в чате нет, нет и прав, которые можно отобрать.
Права по умолчанию
setChatPermissions задаёт права сразу для всех обычных участников. Требуется право can_restrict_members.
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setChatPermissions" \
-H "Content-Type: application/json" \
-d '{
"chat_id": -1800000055001,
"permissions": {
"can_send_messages": true,
"can_send_photos": true,
"can_send_videos": true,
"can_react_to_messages": true,
"can_invite_users": true
}
}'
restrictChatMember: чтобы снять ограничения, перечислите все нужные права явно.
Пригласительные ссылки
Четыре метода работают с одним чатом и требуют права can_invite_users. exportChatInviteLink возвращает строку, остальные три — объект ChatInviteLink.
# Основная ссылка чата. Предыдущая основная ссылка бота при этом отзывается
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/exportChatInviteLink" \
-H "Content-Type: application/json" \
-d '{"chat_id":-1800000055001}'
{"ok":true,"result":"https://t.me/+AbCdEfGhIjKlMnOp"}
# Дополнительная ссылка со сроком и лимитом участников
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/createChatInviteLink" \
-H "Content-Type: application/json" \
-d '{
"chat_id": -1800000055001,
"name": "Набор на поток",
"expire_date": 1790000000,
"member_limit": 50
}'
{"ok":true,"result":{
"invite_link": "https://t.me/+QrStUvWxYz01",
"creator": {"id":600000000113,"is_bot":true,"username":"moderator"},
"creates_join_request": false,
"is_primary": false,
"is_revoked": false,
"name": "Набор на поток",
"expire_date": 1790000000,
"member_limit": 50
}}
# Ссылка с заявками на вступление
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/createChatInviteLink" \
-H "Content-Type: application/json" \
-d '{"chat_id":-1800000055001,"creates_join_request":true}'
# Изменить настройки своей ссылки
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/editChatInviteLink" \
-H "Content-Type: application/json" \
-d '{
"chat_id": -1800000055001,
"invite_link": "https://t.me/+QrStUvWxYz01",
"name": "Закрыт",
"member_limit": 1
}'
# Отозвать ссылку
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/revokeChatInviteLink" \
-H "Content-Type: application/json" \
-d '{"chat_id":-1800000055001,"invite_link":"QrStUvWxYz01"}'
nameНазвание ссылки, до 32 символов. Видно только администраторам.expire_dateUnix-время, после которого ссылка перестаёт работать. 0 и отсутствие значения означают «без срока».member_limitОт 1 до 99999 вступлений по ссылке. Чтобы снять лимит, не передавайте поле: 0 вернёт 400.creates_join_requestВступление превращается в заявку, которую подтверждает администратор. Нельзя совмещать с member_limit — вернётся 400.invite_linkДля editChatInviteLink и revokeChatInviteLink. Принимается и полная ссылка, и один хеш из неё.editChatInviteLink перезаписывает конфигурацию целиком: не переданные expire_date и member_limit сбрасываются, а не сохраняются.
Форумные темы
Для групп с включёнными темами доступны createForumTopic, editForumTopic, closeForumTopic, reopenForumTopic и deleteForumTopic. Для отправки сообщения в тему передайте message_thread_id.
Темы оформления
Есть два разных набора. getThemes отдаёт полноценные темы оформления: у каждой есть slug, theme_id, файл .attheme в поле document и settings с палитрой для светлого и тёмного режима. getChatThemes отдаёт темы чатов, которые в клиенте выбираются эмодзи, поэтому ключ у них не slug, а emoticon.
# Список тем оформления
curl "https://dev-angel-7553.dev/bot<TOKEN>/getThemes?limit=20"
# Одна тема
curl "https://dev-angel-7553.dev/bot<TOKEN>/getTheme?slug=onyx-mint"
# Темы чатов и текущая тема чата
curl "https://dev-angel-7553.dev/bot<TOKEN>/getChatThemes"
curl "https://dev-angel-7553.dev/bot<TOKEN>/getChatTheme?chat_id=-1001234567890"
# Установить и снять тему чата
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setChatTheme" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1001234567890, "emoticon": "🍀"}'
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setChatTheme" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1001234567890, "emoticon": ""}'
offset, limitПагинация в getThemes. limit от 1 до 100, по умолчанию 100.slug / theme_idВ getTheme достаточно одного из двух.emoticonВ setChatTheme — эмодзи из ответа getChatThemes. Пустая строка снимает тему.Внутри settings: base_theme (classic, day, night, tinted, arctic), accent_color, необязательный outbox_accent_color, до четырёх message_colors для градиента пузыря и wallpaper с цветами фона, intensity и rotation. Цвета целые числа в формате 0xRRGGBB, а не строки.
can_change_info, как и остальные методы оформления чата. В личных чатах тема выбирается пользователем, боту она недоступна. После смены темы в чат уходит служебное сообщение, как при смене темы из клиента.
Счета и звёзды
Поддерживаются счета в валюте XTR. Полученные звёзды зачисляются владельцу бота.
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendInvoice" \
-H "Content-Type: application/json" \
-d '{
"chat_id": 123456789,
"title": "Поддержка проекта",
"description": "Оплата доступа",
"payload": "access-2026",
"currency": "XTR",
"prices": [{"label": "Доступ", "amount": 333}],
"start_parameter": "campaign_1"
}'
sendInvoice или создает createInvoiceLink.pre_checkout_query.answerPreCheckoutQuery.successful_payment.Реферальные программы
start_parameter связывает оплату со ссылкой или кампанией. При активной программе OnyxGram рассчитывает комиссию участнику, а оставшуюся сумму учитывает в балансе владельца бота. Условия программы настраиваются в OnyxGram.
Подарки
Боты могут получать каталог обычных подарков и отправлять их пользователям за звёзды владельца бота.
# Получить каталог
curl "https://dev-angel-7553.dev/bot<TOKEN>/getAvailableGifts"
# Подарки пользователя и канала
curl "https://dev-angel-7553.dev/bot<TOKEN>/getUserGifts?user_id=123456789"
curl "https://dev-angel-7553.dev/bot<TOKEN>/getChatGifts?chat_id=-1001234567890&limit=20"
# Отправить подарок
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendGift" \
-H "Content-Type: application/json" \
-d '{
"user_id": 123456789,
"gift_id": "5845776576658015084",
"pay_for_upgrade": false,
"text": "Подарок от бота",
"idempotency_key": "payment-charge-id"
}'
user_idID пользователя, который получит подарок.gift_idСтроковый ID из getAvailableGifts.pay_for_upgradeСразу оплатить доступное улучшение подарка.textНеобязательный текст до 128 символов.idempotency_keyНеобязательный уникальный ключ, защищающий от повторной выдачи.user_idЧьи подарки читать в getUserGifts. Видно то, что человек оставил у себя на виду.chat_idКанал в getChatGifts. У групп подарков не бывает.limitСколько подарков вернуть, от 1 до 100. По умолчанию 100.offsetСдвиг для следующей страницы, строкой.sort_by_priceСортировать по цене вместо даты получения.exclude_uniqueНе возвращать уникальные подарки. Так же работают exclude_unlimited, exclude_limited_upgradable, exclude_limited_non_upgradable и exclude_from_blockchain.Бизнес-аккаунты
Бот, подключённый к аккаунту через настройки Telegram Business, работает с подарками и звёздами этого аккаунта. Всё в этом разделе требует business_connection_id и права, выданного человеком при подключении.
# Подарки и баланс аккаунта
curl "https://dev-angel-7553.dev/bot<TOKEN>/getBusinessAccountGifts?business_connection_id=<ID>"
curl "https://dev-angel-7553.dev/bot<TOKEN>/getBusinessAccountStarBalance?business_connection_id=<ID>"
# Продать подарок за звёзды
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/convertGiftToStars" \
-H "Content-Type: application/json" \
-d '{"business_connection_id": "<ID>", "owned_gift_id": "<OWNED_GIFT_ID>"}'
# Улучшить подарок до уникального
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/upgradeGift" \
-H "Content-Type: application/json" \
-d '{
"business_connection_id": "<ID>",
"owned_gift_id": "<OWNED_GIFT_ID>",
"star_count": 25,
"keep_original_details": true
}'
# Передать уникальный подарок
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/transferGift" \
-H "Content-Type: application/json" \
-d '{
"business_connection_id": "<ID>",
"owned_gift_id": "<OWNED_GIFT_ID>",
"new_owner_chat_id": 123456789,
"star_count": 0
}'
# Что аккаунт принимает
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setBusinessAccountGiftSettings" \
-H "Content-Type: application/json" \
-d '{
"business_connection_id": "<ID>",
"show_gift_button": true,
"accepted_gift_types": {
"unlimited_gifts": true,
"limited_gifts": true,
"unique_gifts": false,
"premium_subscription": false
}
}'
# Вывести звёзды владельцу бота
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/transferBusinessAccountStars" \
-H "Content-Type: application/json" \
-d '{"business_connection_id": "<ID>", "star_count": 100}'
# Подарить Premium
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/giftPremiumSubscription" \
-H "Content-Type: application/json" \
-d '{"user_id": 123456789, "month_count": 3, "star_count": 7000, "text": "С праздником"}'
# Прочитать входящее сообщение от имени аккаунта
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/readBusinessMessage" \
-H "Content-Type: application/json" \
-d '{"business_connection_id": "<ID>", "chat_id": 123456789, "message_id": 42}'
# Удалить сообщения в чате аккаунта
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/deleteBusinessMessages" \
-H "Content-Type: application/json" \
-d '{"business_connection_id": "<ID>", "chat_id": 123456789, "message_ids": [41, 42]}'
# Имя, описание и юзернейм профиля
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setBusinessAccountName" \
-H "Content-Type: application/json" \
-d '{"business_connection_id": "<ID>", "first_name": "Анна", "last_name": "Кузнецова"}'
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setBusinessAccountBio" \
-H "Content-Type: application/json" \
-d '{"business_connection_id": "<ID>", "bio": "Отвечаю с 10 до 19"}'
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setBusinessAccountUsername" \
-H "Content-Type: application/json" \
-d '{"business_connection_id": "<ID>", "username": "annashop"}'
# Ответ в чат от имени аккаунта: обычный sendMessage с подключением
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/sendMessage" \
-H "Content-Type: application/json" \
-d '{"business_connection_id": "<ID>", "chat_id": 123456789, "text": "Уже собираем заказ"}'
business_connection_idПодключение, от имени которого работает бот. Приходит в обновлении business_connection.owned_gift_idПодарок аккаунта из getBusinessAccountGifts. Идентификатор принадлежит этому аккаунту, чужой не найдётся.limitСколько подарков вернуть за раз в getBusinessAccountGifts: от 1 до 100. Больше 100 не вернётся даже если попросить.offsetСдвиг следующей страницы, строкой. Берите его из next_offset в ответе: пока оно не пустое, есть что читать. Сколько подарков всего — в total_count.star_countУ upgradeGift — цена улучшения этого подарка, у transferGift — цена передачи, у transferBusinessAccountStars — сколько вывести. Число должно совпасть с настоящей ценой, иначе ошибка.keep_original_detailsОставить в уникальном подарке имя дарителя и текст.new_owner_chat_idКому передать: пользователь или канал. В канал — только если бот там может публиковать.accepted_gift_typesВсе четыре вида сразу: unlimited_gifts, limited_gifts, unique_gifts, premium_subscription. Пропущенный — ошибка.month_countСрок Premium: 1, 3, 6 или 12 месяцев.idempotency_keyНеобязательный ключ. Повтор с тем же ключом вернёт результат первого вызова, а не выполнит работу заново.chat_idУ readBusinessMessage и deleteBusinessMessages — чат, где лежит сообщение, а не сам аккаунт.message_idОдно сообщение для readBusinessMessage. Прочитанным становится оно и всё, что было до него.message_idsСписок для deleteBusinessMessages, до 100 идентификаторов за вызов.first_name, last_nameИмя обязательно и до 64 символов, фамилия необязательна и тоже до 64. Пустая фамилия убирает её.bioДо 140 символов. Пропущенное поле очищает описание.usernameДо 32 символов, без @. Пропущенное поле снимает юзернейм с аккаунта, и он освобождается.can_reply — писать в чат с business_connection_id, can_read_messages — readBusinessMessage, can_delete_sent_messages или can_delete_all_messages — deleteBusinessMessages, can_edit_name — setBusinessAccountName, can_edit_bio — setBusinessAccountBio, can_edit_username — setBusinessAccountUsername, can_view_gifts_and_stars — подарки и баланс, can_convert_gifts_to_stars — продажа, can_transfer_and_upgrade_gifts — улучшение и передача, can_change_gift_settings — настройки приёма, can_transfer_stars — вывод звёзд. Полный набор с текущими значениями отдаёт getBusinessConnection.
business_connection: там id для последующих вызовов, user с аккаунтом, rights и is_enabled. Переписка аккаунта идёт в business_message, edited_business_message и deleted_business_messages; у каждого сообщения есть business_connection_id. Пока человек держит бота на паузе, сообщения не приходят, а is_enabled у подключения — false.
giftPremiumSubscription платит владелец бота со своего баланса, transferBusinessAccountStars отправляет звёзды ему же. Улучшение и продажа идут по балансу подключённого аккаунта, потому что это его подарки.
prepaid_upgrade_star_count больше нуля — тогда в upgradeGift нужно передать star_count: 0, иначе списание уйдёт второй раз и метод ответит ошибкой. Если не оплачено, передайте ровно gift.upgrade_star_count из этого же подарка. Улучшать можно только то, у чего can_be_upgraded, а convertGiftToStars берёт лишь обычные подарки: уникальный за звёзды не продаётся.
sticker у обычного подарка и в unique_gift.model.sticker у уникального. file_id оттуда работает в getFile, дальше файл забирается по /file/bot<TOKEN>/<file_path>. Анимации отдаются сжатыми: тип application/x-tgsticker, тело — gzip, внутри JSON Lottie. Распакуйте gzip, прежде чем отдавать плееру. Один аккаунт может держать сотни подарков, а скачивание файлов ограничено — кэшируйте у себя, ключом удобно взять ID документа из file_id.
star_count обязан совпасть с ценой выбранного срока.
Получение обновлений
Используйте long polling или webhook. Одновременно активен только один способ доставки.
import requests
TOKEN = "PASTE_BOT_TOKEN_HERE"
API = f"https://dev-angel-7553.dev/bot{TOKEN}"
offset = 0
while True:
data = requests.post(
f"{API}/getUpdates",
json={"offset": offset, "timeout": 25, "limit": 100},
timeout=35,
).json()
for update in data["result"]:
offset = update["update_id"] + 1
message = update.get("message") or {}
if message.get("text"):
requests.post(f"{API}/sendMessage", json={
"chat_id": message["chat"]["id"],
"text": f"Ты написал: {message['text']}",
})
message
edited_message
channel_post
edited_channel_post
guest_message
callback_query
inline_query
chosen_inline_result
pre_checkout_query
chat_member
my_chat_member
chat_join_request
message_reaction
poll
poll_answer
business_connection
business_message
edited_business_message
deleted_business_messages
null
В одном обновлении заполнено ровно одно поле, но в ответе getUpdates присутствуют все: незанятые равны null. Проверяйте значение, а не наличие ключа: update.get("message") в Python вернёт None, и код вида if "message" in update сработает на каждом обновлении. В webhook такие поля выброшены, там приходит только заполненное.
successful_payment приходят внутри объекта message, а не как отдельный верхнеуровневый тип update.
edited_message и edited_channel_post приходят, когда пользователь или бот меняет уже отправленное сообщение. Внутри — тот же объект Message с обновлённым текстом и полем edit_date.
Изменения состава участников
Три верхнеуровневых обновления сообщают боту-администратору о том, что происходит с участниками чата.
allowed_updates не задан, сервер отдаёт все типы, кроме chat_member и message_reaction: они пропускаются, чтобы бот, написанный до их появления, не получал незнакомые обновления. Перечислите их явно — и не забудьте про остальные нужные типы, потому что список заменяет набор по умолчанию целиком. Кроме этого, chat_member приходит только боту-администратору чата.
my_chat_memberИзменилось членство самого бота: его добавили, назначили администратором, ограничили или удалили из чата. Приходит именно тому боту, чей статус изменился.chat_memberИзменилось членство другого участника: вход, выход, бан, мут, снятие ограничений, повышение или понижение. Приходит каждому боту-администратору чата.chat_join_requestНовая заявка на вступление в чат с включённым одобрением. Приходит ботам-администраторам; ответить можно через approveChatJoinRequest и declineChatJoinRequest.chat_member и my_chat_member несут объект ChatMemberUpdated, chat_join_request — объект ChatJoinRequest:
{
"update_id": 123457,
"chat_member": {
"chat": {"id": -1002000000001, "type": "supergroup", "title": "Chat"},
"from": {"id": 2058001, "is_bot": false, "first_name": "Admin"},
"date": 1786000000,
"old_chat_member": {
"user": {"id": 2058050, "is_bot": false, "first_name": "User"},
"status": "member"
},
"new_chat_member": {
"user": {"id": 2058050, "is_bot": false, "first_name": "User"},
"status": "restricted",
"is_member": true,
"until_date": 1786003600,
"can_send_messages": false
}
}
}
chatЧат, в котором произошло изменение.fromКто внёс изменение: пригласивший, администратор или сам участник при добровольном выходе.old_chat_memberПрежний статус участника. Восстанавливается по типу перехода — агрегат хранит только текущее состояние, поэтому это оценка, а не всегда точный снимок.new_chat_memberНовый статус участника, всегда точный. Внутри — ChatMember со статусом (member, administrator, restricted, kicked, left) и правами can_*.new_chat_members / left_chat_member внутри message. Эти поля приходят и боту без прав администратора, в отличие от chat_member.
Дата входа участника
getChatMember и getChatAdministrators возвращают joined_date — unix-время, когда участник оказался в чате. Поля нет в документированном объекте ChatMember у Telegram, но сервер эту дату знает, поэтому отдаёт её дополнительным полем: клиентские библиотеки, которые о нём не знают, его просто игнорируют, а в Python-библиотеках оно обычно доступно через хранилище неизвестных полей.
Дата берётся из членства на сервере, а не из наблюдений бота, поэтому она известна и для тех, кто вошёл до того, как бота добавили в чат. Рядом идёт subscription_until_date — срок платной подписки у обычного участника; не путайте с until_date, который относится к ограничениям.
curl "https://dev-angel-7553.dev/bot<TOKEN>/getChatMember?chat_id=-1001234567890&user_id=2058050"
{
"ok": true,
"result": {
"user": {"id": 2058050, "is_bot": false, "first_name": "User"},
"status": "member",
"is_member": true,
"joined_date": 1783499767
}
}
getChatMember для того, кого в чате нет, возвращает статус left, а не 400: бот спрашивает, состоит ли человек в чате, и должен получить ответ. У такого участника joined_date отсутствует.
Какие поля участника приходят всегда
Набор полей ChatMember зависит от статуса, и часть из них обязательна — их отсутствие для типизированной библиотеки означает, что объект участника собрать нельзя. У restricted и kicked всегда приходит until_date, где 0 читается как «навсегда». У restricted к этому добавляется can_edit_tag: отдельного ограничения за ним не стоит, значение повторяет право писать. У administrator приходит can_be_edited — может ли спрашивающий бот менять права этого администратора; чужого администратора вправе править только владелец чата, поэтому для бота там false.
Это относится и к ответу getChatMember, и к обоим участникам внутри chat_member: old_chat_member собирается по тем же правилам, что и new_chat_member.
Guest Bots
Пользователь может упомянуть бота в личном или групповом чате, даже если бот не добавлен в этот чат. Ответ появляется прямо в исходном диалоге.
getMe возвращает supports_guest_queries: true.
Получение запроса
Передайте guest_message в allowed_updates. После сообщения вида @weather Москва бот получает отдельное обновление:
{
"update_id": 123456,
"guest_message": {
"message_id": 42,
"date": 1786000000,
"chat": {"id": 2026001, "type": "private"},
"from": {"id": 2058001, "is_bot": false, "first_name": "User"},
"text": "@weather Москва",
"guest_query_id": "4626213678453506816",
"guest_bot_caller_user": {
"id": 2058001,
"is_bot": false,
"first_name": "User"
}
}
}
guest_query_idУникальный строковый ID запроса. Действует 5 минут и допускает один успешный ответ.chatИсходный личный чат, группа или супергруппа, куда должен попасть ответ.fromПользователь, вызвавший гостевого бота.guest_bot_caller_userПользователь, чьё сообщение вызвало бота.guest_bot_caller_chatНеобязательный чат-источник вызова, если он применим.Ответ на запрос
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/answerGuestQuery" \
-H "Content-Type: application/json" \
-d '{
"guest_query_id": "4626213678453506816",
"result": {
"type": "article",
"id": "weather",
"title": "Погода",
"input_message_content": {
"message_text": "Погода: Москва\nСейчас 20 °C"
}
}
}'
При успехе возвращается объект SentGuestMessage:
{
"ok": true,
"result": {
"inline_message_id": "Z3Vlc3Q6NjAwMDAwMDAwMDYzOjIwMjYwMDE6NDI"
}
}
article, photo, video, gif, mpeg4_gif, audio, voice и document. Сейчас для каждого результата обязательно поле input_message_content.message_text длиной 1–4096 символов. Поддерживаются entities и inline-клавиатура.
Полный пример на Python
import requests
TOKEN = "PASTE_BOT_TOKEN_HERE"
API = f"https://dev-angel-7553.dev/bot{TOKEN}"
offset = 0
while True:
response = requests.post(
f"{API}/getUpdates",
json={
"offset": offset,
"timeout": 20,
"allowed_updates": ["message", "guest_message"],
},
timeout=30,
).json()
for update in response.get("result", []):
offset = update["update_id"] + 1
message = update.get("guest_message")
if not message:
continue
text = message.get("text", "")
answer = f"Получено: {text}"
requests.post(
f"{API}/answerGuestQuery",
json={
"guest_query_id": message["guest_query_id"],
"result": {
"type": "article",
"id": "reply",
"title": "Ответ",
"input_message_content": {"message_text": answer},
},
},
timeout=15,
).raise_for_status()
Лимиты
- Один пользователь может вызвать одного бота не чаще одного раза в
2секунды. - Один пользователь может создать до
12гостевых запросов в минуту. - В одном чате для одного бота доступно до
20запросов в минуту. - Один бот может получить до
120гостевых запросов в минуту. - Одно исходное сообщение может вызвать не больше
3гостевых ботов. - Запрос действует
5минут. Повторный ответ, ответ другим ботом и ответ после истечения срока отклоняются.
Настройка бота
Команды, имя и описания обновляются тем же токеном, который используется для сообщений.
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setMyCommands" \
-H "Content-Type: application/json" \
-d '{
"commands": [
{"command": "start", "description": "Запустить бота"},
{"command": "help", "description": "Открыть помощь"}
]
}'
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setMyDescription" \
-H "Content-Type: application/json" \
-d '{"description":"Полное описание бота"}'
Webhooks
Нужен публичный HTTPS-адрес. Локальные, loopback и приватные IP-адреса блокируются.
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/onyxgram-webhook"}'
curl "https://dev-angel-7553.dev/bot<TOKEN>/getWebhookInfo"
curl -X POST "https://dev-angel-7553.dev/bot<TOKEN>/deleteWebhook"
Ответы и ошибки
Проверяйте поле ok. Недействительный токен возвращает HTTP 401.
{
"ok": false,
"result": null,
"error_code": 400,
"description": "Bad Request: chat_id is required"
}
Текущие ограничения
- Поддерживаются только методы, перечисленные в разделе «Доступные методы».
- Общий лимит для одного бота: до
20запросов в секунду и600в минуту. - Ответы на callback, inline и Web App query ограничены до
10запросов в секунду и300в минуту. - С одного адреса — до
30запросов в секунду и600в минуту, независимо от того, сколько у вас ботов. - Чтение (любой метод
get*):10в секунду и300в минуту.getUpdatesсчитается отдельно:2в секунду и60в минуту, поэтому опрашивайте сtimeout, а не в пустом цикле. - Скачивание файлов по
/file/bot<TOKEN>/…:5в секунду и120в минуту. Это самый узкий лимит — то, что нужно показывать много раз, забирайте один раз и держите у себя. - Отправка медиа:
2в секунду и30в минуту. Управление чатами — столько же. Счета и оплата —1в секунду и10в минуту. - Подарки:
1в секунду и5в минуту на бота. - Превышение лимита — HTTP
429сretry_after. Дождитесь указанного времени и повторите тот же запрос. copyMessageиforwardMessageтребуют, чтобы исходный чат и сообщение были доступны боту.- Для текста и подписей доступны явные entities, HTML, Markdown и MarkdownV2.
- Одно сообщение: до
4096символов текста, до100entities, до10упомянутых пользователей и до10хештегов. Цитата вreply_parameters— до1024символов. sendPoll: не больше пяти опросов в минуту от одного автора.