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 |
Забагато запитів — зачекайте й повторіть. |
Текст помилок у
description— російською, як і в решті API сайту.
Як бот отримує повідомлення
Усе, що відбувається з ботом, приходить оновленнями (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 під час видалення повідомлення в групі. Видаляти чужі повідомлення й виключати учасників бот може, лише якщо власник чату призначив його адміністратором.
Див. також: Боти для користувачів, Розробникам ігор.