Bot API — боти для розробників

Як зробити бота для MRIYU: токен, повідомлення, кнопки, фото й файли, боти в групах і каналах, вебхуки, ліміти й готові приклади.

Бот — це сторінка-програма. Люди листуються з нею в месенджері, а відповідає ваш код: він отримує повідомлення через Bot API й надсилає відповіді. Якщо ви робили ботів для Telegram, усе буде знайомим.

Що вміє бот:

  • відповідати на повідомлення й команди (/start, /help і свої);
  • надсилати повідомлення з кнопками: відповідь боту, посилання на сайт або відкриття гри / Mini App у MRIYU;
  • змінювати й видаляти свої повідомлення;
  • надсилати фото й файли;
  • розсилати сповіщення тим, хто на нього підписаний;
  • працювати в групових чатах і каналах: відповідати на команди, вітати новачків, модерувати, публікувати пости (автопостинг);
  • показувати кнопку меню, яка відкриває вашу гру або Mini App.

Бот може писати лише тим, хто сам натиснув «Почати» або написав йому. Першим незнайомій людині бот не напише — тому в MRIYU немає спаму від ботів.

Швидкий старт за 5 хвилин

  1. Відкрийте «Розробникам» у меню ліворуч (пункт приховано — увімкніть його в «Налаштуванні пунктів меню», див. Налаштування та меню, або відкрийте одразу mriyu.com/developers?bots) → вкладка «Боти».
  2. Натисніть «Новий бот»: вкажіть ім’я, адресу (латиниця, цифри, _, у кінці обов’язково bot, наприклад weather_bot) і кілька слів про бота.
  3. Скопіюйте токен — він показується один раз. Токен — це пароль бота.
  4. У вкладці «Підключення» скопіюйте готовий код (там уже підставлено ваш токен) і запустіть його.
  5. Відкрийте 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 під час видалення повідомлення в групі. Видаляти чужі повідомлення й виключати учасників бот може, лише якщо власник чату призначив його адміністратором.

Див. також: Боти для користувачів, Розробникам ігор.