Bot API — боты для разработчиков
Как сделать бота для MRIYU: токен, сообщения, кнопки, фото и файлы, боты в группах и каналах, вебхуки, лимиты и готовые примеры.
Бот — это страница-программа. Люди переписываются с ней в мессенджере, а отвечает ваш код: он получает сообщения через Bot API и отправляет ответы. Если вы делали ботов для Telegram, всё будет знакомо.
Что умеет бот:
- отвечать на сообщения и команды (
/start,/helpи свои); - присылать сообщения с кнопками: ответ боту, ссылка на сайт или открытие игры / Mini App в MRIYU;
- менять и удалять свои сообщения;
- присылать фото и файлы;
- рассылать уведомления тем, кто на него подписан;
- работать в групповых чатах и каналах: отвечать на команды, приветствовать новичков, модерировать, публиковать посты (автопостинг);
- показывать кнопку меню, которая открывает вашу игру или Mini App.
Бот может писать только тем, кто сам нажал «Начать» или написал ему. Первым незнакомому человеку бот не напишет — так в MRIYU нет спама от ботов.
Быстрый старт за 5 минут
- Откройте «Разработчикам» в меню слева (пункт скрыт — включите его в «Настройке пунктов меню», см. Настройки и меню, или откройте сразу
mriyu.com/developers?bots) → вкладка «Боты». - Нажмите «Новый бот»: укажите имя, адрес (латиница, цифры,
_, в конце обязательноbot, напримерweather_bot) и пару слов о боте. - Скопируйте токен — он показывается один раз. Токен — это пароль бота.
- Во вкладке «Подключение» скопируйте готовый код (там уже подставлен ваш токен) и запустите его.
- Откройте
mriyu.com/<адрес бота>, нажмите «Открыть бота» → «Начать» и напишите что-нибудь — бот ответит.
Как устроены запросы
Адрес каждого метода:
https://mriyu.com/api/bot/v1/<метод>
- Запрос —
POSTс телом в JSON (Content-Type: application/json). Методы без параметров можно вызывать иGET. - Токен — в заголовке
Authorization: Bearer <токен>. Можно также заголовкомX-Bot-Tokenили параметром?token=(не советуем: адрес с токеном может попасть в журналы). - Ответ всегда в JSON.
Успех:
{"ok": true, "result": { ... }}
Ошибка:
{"ok": false, "error_code": 403, "description": "Пользователь не нажимал «Начать» или остановил бота."}
| Код | Когда |
|---|---|
400 |
Неверные параметры (в description — что именно). |
401 |
Неверный токен или бот заблокирован администрацией. |
403 |
Нельзя писать этому человеку: он не нажимал «Начать», остановил бота или заблокировал его. |
404 |
Нет такого метода, пользователя или сообщения. |
409 |
getUpdates при включённом вебхуке. |
422 |
Неверные кнопки (подробности — в description). |
429 |
Слишком много запросов — подождите и повторите. |
Как бот получает сообщения
Всё, что происходит с ботом, приходит обновлениями (update). Есть два способа их получать — выберите один.
Способ 1. getUpdates — без своего сайта
Ваш код раз в 1–3 секунды спрашивает: «есть что-то новое?». Подходит любой компьютер, VPS или хостинг — открытый адрес не нужен.
- Обновления хранятся 24 часа.
- Передавайте
offset=update_idпоследнего обработанного обновления + 1 — всё, что раньше, считается полученным и больше не придёт.
Способ 2. Вебхук — сообщения приходят сразу
MRIYU сам отправляет каждое обновление POST-запросом на ваш адрес. Нужен сайт с https.
- Включить: метод
setWebhookили кабинет → бот → «Настройки» → «Вебхук». Кнопка «Проверить вебхук» пришлёт пробное обновление{"update_id": 0, "type": "ping"}. - Если указали секрет, он приходит в заголовке
X-Mriyu-Bot-Secret— проверяйте его, чтобы чужие не слали вам поддельные обновления. - Ваш сервер должен ответить кодом 2xx за 5 секунд. Отвечайте сразу, а долгую работу делайте после ответа.
- Не ответил или ошибка — доставка остановится и повторится через минуту, порядок обновлений сохранится. Ошибка видна в кабинете и в
getWebhookInfo. - Пока вебхук включён,
getUpdatesнедоступен (ошибка409).
Виды обновлений
Каждое обновление — JSON с полями update_id (растёт по порядку) и type. Поле from — кто это сделал: {"id": 15, "name": "Оля Петренко", "username": "olya"}.
| type | Когда приходит | Поля |
|---|---|---|
start |
Человек нажал «Начать» | from, payload — параметр из ссылки ?start= или null |
message |
Человек написал боту | from, message |
button |
Нажал кнопку с data под сообщением бота |
from, button: {message_id, data} |
stop |
Нажал «Остановить бота» | from |
chat_message |
Сообщение в групповом чате или канале, где есть бот (см. «Боты в группах») | chat, from, message |
chat_added |
Бота добавили в чат или канал | chat, by — кто добавил |
chat_removed |
Бота удалили из чата | chat, by |
chat_join |
В чат пришёл новый участник | chat, user, by — кто пригласил или null |
chat_leave |
Участник вышел или его удалили | chat, user, by |
Поле chat — {"id": 7, "title": "Двор на Шевченко", "type": "chat"} (type: chat — групповой чат, channel — канал). Нажатие кнопки под сообщением бота в группе приходит обновлением button с полем chat.
Поля message:
| Поле | Что это |
|---|---|
id |
Номер сообщения |
text |
Текст |
kind |
Вид: text (бот получает текстовые сообщения) |
command |
Если текст начинается с /: {"name": "forecast", "args": "Киев"} для /forecast Киев, иначе null |
reply_to |
Номер сообщения, на которое ответили, или null |
date |
Время, unix-секунды |
Пример обновления:
{
"update_id": 1042,
"type": "message",
"from": {"id": 15, "name": "Оля Петренко", "username": "olya"},
"message": {"id": 98761, "text": "/forecast Киев", "kind": "text",
"command": {"name": "forecast", "args": "Киев"}, "reply_to": null, "date": 1760524800}
}
Методы
getMe
Проверить токен и узнать о боте. Параметров нет. Ответ: id, name, username, about, verified (галочка «Официальный»), webhook (включён ли), subscribers (сколько людей нажали «Начать»).
sendMessage
Отправить сообщение человеку.
| Параметр | Обязательно | Что это |
|---|---|---|
user_id |
да | Кому — from.id из обновления |
text |
да | Текст до 4000 символов. Разметка как в мессенджере: **жирный**, __курсив__, ссылки [текст](https://…), моноширинный текст — в обратных кавычках |
buttons |
нет | Кнопки под сообщением (см. ниже) |
reply_to |
нет | Номер сообщения, на которое бот отвечает |
silent |
нет | true — без звука уведомления |
Ответ — отправленное сообщение: {"id", "user_id", "text", "buttons", "date", "edited"}. Запомните id, чтобы потом изменить сообщение.
editMessage
Изменить своё сообщение: message_id и новые text и/или buttons. Передайте "buttons": null, чтобы убрать кнопки. Удобно после нажатия кнопки: «Подписаться?» → «Подписка оформлена ✅».
deleteMessage
Удалить своё сообщение: message_id.
getUpdates
Забрать обновления (только без вебхука). Параметры: offset — с какого update_id (всё раньше считается полученным), limit — сколько, до 100 (по умолчанию 100). Ответ — массив обновлений.
setWebhook / deleteWebhook / getWebhookInfo
setWebhook:url(https) и необязательныйsecret(8–128 символов: латиница, цифры,_,-).deleteWebhook: выключить вебхук и вернуться кgetUpdates.getWebhookInfo:url,has_secret,pending(сколько ждут доставки),last_error,last_error_at.
setCommands / getCommands
Список команд — его видят в чате кнопкой «Команды». До 30 команд: {"command": "forecast", "description": "Прогноз на завтра"}. Имя команды — латиница, цифры и _, до 32 символов, без /. То же можно настроить в кабинете.
getUser
Сведения о человеке, который писал боту: user_id → id, name, username, avatar, started (подписан ли сейчас).
sendPhoto / sendDocument
Фото или файл — человеку (user_id) или в чат (chat_id).
| Параметр | Обязательно | Что это |
|---|---|---|
user_id или chat_id |
да | Кому или куда |
file или url |
да | Сам файл (запрос multipart/form-data) или ссылка https — MRIYU скачает файл сам |
caption |
нет | Подпись до 1000 символов |
buttons |
нет | Кнопки; в multipart/form-data — строкой JSON |
reply_to, silent |
нет | Как у sendMessage |
sendPhoto принимает только картинки (jpg, png, webp, gif). Размер — до лимита загрузок сайта. Программы, скрипты и HTML отправить нельзя. В группах и каналах действует фильтр откровенных картинок.
curl -X POST https://mriyu.com/api/bot/v1/sendPhoto \
-H "Authorization: Bearer ВАШ_ТОКЕН" \
-F user_id=15 -F caption="Погода на завтра" -F file=@forecast.png
getSubscribers
Кто подписан на бота — для рассылок. По 1000 номеров: {"user_ids": [...], "next": 5012}. Если next не null, запросите следующую страницу с after = next.
Боты в группах и каналах
Бота можно добавить в групповой чат или канал: владелец или администратор открывает «Участники» → «Добавить бота» и вводит адрес бота. Разработчик может это запретить: кабинет → бот → «Настройки» → снять «Можно добавлять в группы и каналы».
- В групповом чате бот становится обычным участником. Владелец может сделать его администратором («Назначить администратором») — тогда бот сможет модерировать.
- В канал бот сразу добавляется администратором — он может публиковать посты (автопостинг).
Что бот видит в группе
По умолчанию — как режим приватности в Telegram — бот получает только:
- команды:
/rules,/help Киев(команда/start@other_botдостанется только ботуother_bot); - упоминания: сообщения, где есть
@адрес_бота; - ответы на его собственные сообщения.
Если боту нужно видеть всё (например, чтобы удалять спам), включите в кабинете «Видит все сообщения в группах». Люди в чате об этом не узнают — включайте, только если это действительно нужно.
Методы для групп
| Метод | Параметры | Что делает |
|---|---|---|
getChats |
— | Чаты и каналы, где состоит бот: [{id, title, type, role}] |
getChat |
chat_id |
Чат: id, title, type, role бота, members |
sendChatMessage |
chat_id, text, buttons, reply_to, silent |
Сообщение в чат; в канал — только если бот администратор |
editChatMessage |
chat_id, message_id, text, buttons |
Изменить своё сообщение |
deleteChatMessage |
chat_id, message_id |
Удалить своё сообщение; чужое — если бот администратор |
kickChatMember |
chat_id, user_id |
Исключить участника (бот — администратор; владельца и администраторов исключить нельзя) |
sendPhoto, sendDocument |
chat_id вместо user_id |
Фото или файл в чат |
Ответ sendChatMessage: {"id", "chat_id", "kind", "text", "url", "buttons", "date"}.
Пример: страж чата (Node.js)
Бот-администратор с «Видит все сообщения»: приветствует новичков, удаляет ссылки и отвечает на /rules.
async function handle(update) {
if (update.type === 'chat_join') {
await call('sendChatMessage', {chat_id: update.chat.id, text: 'Привет, ' + update.user.name + '! Правила — /rules'});
}
if (update.type === 'chat_message') {
const {chat, message} = update;
if (/https?:\/\//i.test(message.text)) {
await call('deleteChatMessage', {chat_id: chat.id, message_id: message.id});
await call('sendChatMessage', {chat_id: chat.id, text: 'Ссылки в этом чате запрещены.'});
} else if (message.command?.name === 'rules') {
await call('sendChatMessage', {chat_id: chat.id, text: '1. Без спама\n2. Без оскорблений', reply_to: message.id});
}
}
}
Пример: автопостинг в канал (Python)
import requests
HEADERS = {'Authorization': 'Bearer ВАШ_ТОКЕН'}
API = 'https://mriyu.com/api/bot/v1/'
chats = requests.post(API + 'getChats', headers=HEADERS).json()['result']
channel = next(c for c in chats if c['type'] == 'channel')
requests.post(API + 'sendPhoto', headers=HEADERS, data={
'chat_id': channel['id'], 'caption': 'Новости дня', 'url': 'https://example.com/today.jpg',
})
Кнопки
buttons — массив рядов, в ряду — массив кнопок. До 8 рядов, в ряду от 1 до 4 кнопок, текст кнопки — до 40 символов. Каждая кнопка — одно из трёх:
| Кнопка | Что происходит при нажатии |
|---|---|
{"text": "Да", "data": "sub:yes"} |
Боту приходит обновление button с этим data (до 64 байт). Ответьте новым сообщением или измените это (editMessage). |
{"text": "Сайт", "url": "https://example.com"} |
Открывается ссылка (только https) в новой вкладке. |
{"text": "Играть", "app": "my-game"} |
Открывается игра или Mini App MRIYU по её адресу. |
"buttons": [
[{"text": "✅ Да", "data": "sub:yes"}, {"text": "❌ Нет", "data": "sub:no"}],
[{"text": "🎮 Открыть игру", "app": "my-game"}]
]
Публичная страница бота
У бота есть своя страница — mriyu.com/<адрес бота>. Её настраивают в кабинете → бот → «Настройки» → «Публичная страница»:
- обложка и аватар;
- статус — строка под именем (до 140 символов);
- категория — «Новости», «Погода», «Игры», «Инструменты», «Покупки», «Обучение», «Развлечения», «Поддержка», «Сообщества» или «Другое»;
- сайт — ссылка на ваш сайт;
- «Что умеет бот» — описание, оно видно на странице и в пустом чате.
На странице также видны команды, сколько людей пользуются ботом, разработчик и кнопки «Открыть бота» и кнопка меню.
Команды, кнопка меню и ссылка с параметром
- Команды. Над полем ввода в чате с ботом есть кнопка «Команды» — список из
setCommands. Нажатие отправляет команду, вам приходитmessageс заполненнымcommand. - Кнопка меню. В кабинете → «Настройки» укажите адрес игры или Mini App (например
my-game) и текст кнопки — рядом с «Командами» появится кнопка, открывающая её. - Ссылка с параметром.
mriyu.com/weather_bot?start=promo42— после «Начать» вы получите обновлениеstartс"payload": "promo42". Параметр — до 64 символов: латиница, цифры,_,-. Удобно для реферальных ссылок и рекламы.
Лимиты
| Что | Сколько |
|---|---|
| Сообщений от бота | 30 в секунду всего, 20 в минуту одному человеку, 20 в минуту в один чат |
| Запросов к API с одного IP | 600 в минуту |
| Хранение обновлений | 24 часа |
| Ответ вебхука | 5 секунд |
| Ботов у одного разработчика | 20 |
Превысили — ответ 429: подождите и повторите. Для рассылки многим людям отправляйте по 25–30 сообщений в секунду.
Готовые примеры
Node.js (18+), без сервера — getUpdates
const TOKEN = 'ВАШ_ТОКЕН';
const call = (method, data = {}) => fetch('https://mriyu.com/api/bot/v1/' + method, {
method: 'POST',
headers: {'Authorization': 'Bearer ' + TOKEN, 'Content-Type': 'application/json'},
body: JSON.stringify(data),
}).then((r) => r.json());
let offset = 0;
async function loop() {
const {ok, result} = await call('getUpdates', {offset});
if (ok) {
for (const update of result) {
offset = update.update_id + 1;
if (update.type === 'start') {
await call('sendMessage', {
user_id: update.from.id,
text: 'Привет, **' + update.from.name + '**! Подписаться на прогноз?',
buttons: [[{text: 'Да', data: 'yes'}, {text: 'Нет', data: 'no'}]],
});
} else if (update.type === 'button') {
await call('editMessage', {
message_id: update.button.message_id,
text: update.button.data === 'yes' ? 'Подписка оформлена ✅' : 'Хорошо, не будем.',
buttons: null,
});
} else if (update.type === 'message') {
await call('sendMessage', {user_id: update.from.id, text: 'Вы написали: ' + update.message.text});
}
}
}
setTimeout(loop, 1500);
}
loop();
PHP — вебхук
<?php
// Файл https://example.com/mriyu-bot.php — укажите его адрес в setWebhook.
const TOKEN = 'ВАШ_ТОКЕН';
const SECRET = 'ВАШ_СЕКРЕТ_ВЕБХУКА';
if (($_SERVER['HTTP_X_MRIYU_BOT_SECRET'] ?? '') !== SECRET) { http_response_code(403); exit; }
$update = json_decode(file_get_contents('php://input'), true);
http_response_code(200);
function call(string $method, array $data): array {
$ch = curl_init('https://mriyu.com/api/bot/v1/' . $method);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . TOKEN, 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($data),
]);
return json_decode(curl_exec($ch), true);
}
if (($update['type'] ?? '') === 'message') {
$command = $update['message']['command']['name'] ?? null;
$text = $command === 'help' ? 'Я умею: /forecast <город>' : 'Напишите /help';
call('sendMessage', ['user_id' => $update['from']['id'], 'text' => $text]);
}
Python 3 — getUpdates
import time, requests
TOKEN = 'ВАШ_ТОКЕН'
API = 'https://mriyu.com/api/bot/v1/'
HEADERS = {'Authorization': 'Bearer ' + TOKEN}
def call(method, **data):
return requests.post(API + method, json=data, headers=HEADERS, timeout=10).json()
offset = 0
while True:
answer = call('getUpdates', offset=offset)
for update in answer.get('result', []):
offset = update['update_id'] + 1
if update['type'] == 'message':
call('sendMessage', user_id=update['from']['id'], text='Эхо: ' + update['message']['text'])
time.sleep(1.5)
curl — проверить токен и отправить сообщение
curl -X POST https://mriyu.com/api/bot/v1/getMe -H "Authorization: Bearer ВАШ_ТОКЕН"
curl -X POST https://mriyu.com/api/bot/v1/sendMessage \
-H "Authorization: Bearer ВАШ_ТОКЕН" -H "Content-Type: application/json" \
-d '{"user_id": 15, "text": "Привет!", "buttons": [[{"text": "Сайт", "url": "https://example.com"}]]}'
Безопасность и правила
- Токен — пароль бота. Не публикуйте его в открытом коде и на клиенте (в браузере, в приложении). Утёк — кабинет → бот → «Подключение» → «Новый токен»: старый перестанет работать сразу.
- Проверяйте
X-Mriyu-Bot-Secretв вебхуке. - Бот получает имя и адрес страницы тех, кто ему пишет. Не собирайте лишнего и не передавайте эти данные третьим лицам.
- Запрещены спам и рассылки тем, кто не просил, мошенничество, сбор паролей и платёжных данных, контент 18+.
- Пользователи могут пожаловаться на бота (в чате «⋯» → «Пожаловаться на бота»). За нарушения администрация блокирует бота — токен перестаёт работать, а причина видна в кабинете.
- Проверенным ботам администрация ставит галочку «Официальный».
Чего пока нет
- Голосовые и видео от бота.
- Платежи через бота.
Частые вопросы
Бот не отвечает. Проверьте токен (getMe). Без вебхука — запущен ли ваш код с getUpdates. С вебхуком — getWebhookInfo: если там last_error, ваш сервер не ответил 2xx за 5 секунд.
403 при отправке. Человек не нажимал «Начать», остановил бота или заблокировал его. Ждите, пока он сам напишет.
Обновления приходят повторно. С getUpdates передавайте offset = последний update_id + 1. С вебхуком — отвечайте 2xx: иначе обновление придёт снова.
Как сделать рассылку? getSubscribers → для каждого sendMessage, не быстрее 30 в секунду. Для большой аудитории удобнее канал: добавьте бота администратором и публикуйте через sendChatMessage.
Бот в группе не реагирует на сообщения. Без «Видит все сообщения» он получает только команды, упоминания @адрес_бота и ответы на свои сообщения.
403 при удалении сообщения в группе. Удалять чужие сообщения и исключать участников бот может, только если владелец чата назначил его администратором.
См. также: Боты для пользователей, Разработчикам игр.