Методы
Все методы — под адресом https://api.bot.marx.moscow/api/bot/v1/, с заголовком Authorization: Bearer marx_pat_….
В примерах $MARX_TOKEN — токен бота, $CHAT_ID — номер чата из GET /chats или из обновления, $MESSAGE_ID — номер сообщения. Задайте их в оболочке перед запуском:
export MARX_TOKEN=marx_pat_...
export CHAT_ID=812
export MESSAGE_ID=90211
| Метод | Путь | Что делает |
|---|---|---|
GET | /me | Аккаунт бота |
GET | /chats | Чаты, в которых состоит бот |
POST | /messages | Отправить сообщение |
POST | /media | Загрузить картинку, видео или файл |
POST | /reactions | Поставить или снять реакцию |
POST | /channels | Создать свой канал |
GET | /updates | Получить обновления (длинный опрос) |
POST, DELETE | /webhook | Задать или снять вебхук |
PUT, GET, DELETE | /commands | Команды бота в меню приложения |
GET /me
Аккаунт, которому принадлежит токен. Удобно для проверки токена при запуске.
| Поле ответа | Тип | Что это |
|---|---|---|
user_id | целое | Номер аккаунта бота |
username | строка | Имя пользователя без @ |
display_name | строка | Имя, которое видят в чатах |
token_name | строка | Имя токена; у токена от @marxbot — bot |
is_bot | логическое | true у бота |
curl https://api.bot.marx.moscow/api/bot/v1/me \
-H "Authorization: Bearer $MARX_TOKEN"
{"user_id": 41207, "username": "dacha_weather_bot", "display_name": "Погода на даче", "token_name": "bot", "is_bot": true}
GET /chats
Все чаты, в которых состоит бот, в порядке списка чатов приложения.
| Поле элемента | Тип | Что это |
|---|---|---|
id | целое | Номер чата, chat_id в других методах |
type | строка | direct — личный, group — группа, channel — канал |
title | строка или null | Название; у личного чата null |
curl https://api.bot.marx.moscow/api/bot/v1/chats \
-H "Authorization: Bearer $MARX_TOKEN"
[{"id": 812, "type": "group", "title": "Дача"}, {"id": 977, "type": "direct", "title": null}]
POST /messages
Отправить сообщение в чат, где бот — участник с правом писать. В группе это право у участников есть по умолчанию, в канале — только у администратора. Начать личный чат бот не может: он появляется, когда человек пишет боту.
| Поле запроса | Тип | Что это |
|---|---|---|
chat_id | целое, обязательно | Номер чата |
kind | строка | text (по умолчанию), image, video, file или poll |
body | строка | Текст, до 8192 символов; для text не может быть пустым |
media_id | целое | Для image, video, file: номер из POST /media этого же бота |
caption | строка | Подпись к картинке, видео или файлу, до 8192 символов |
file_name, file_size | строка, целое | Имя и размер файла для file |
question | строка | Для poll: вопрос, до 300 символов |
options | массив строк | Для poll: от 2 до 10 вариантов, каждый до 100 символов; пустые отбрасываются |
anonymous, multiple, revote | логическое | Для poll: анонимный (по умолчанию да), несколько ответов (нет), можно переголосовать (да) |
client_id | строка | До 64 символов. Повтор с тем же client_id в течение часа не создаёт второе сообщение и не расходует предел |
composed_at_ms | целое | Возвращается в ответе как есть |
| Поле ответа | Что это |
|---|---|
message_id | Номер сообщения |
duplicate | true, если это повтор по client_id; тогда в ответе только message_id и duplicate |
message | Сообщение, тот же объект, что в обновлении |
composed_at_ms | Значение из запроса или null |
Текст
curl https://api.bot.marx.moscow/api/bot/v1/messages \
-H "Authorization: Bearer $MARX_TOKEN" \
-H "Content-Type: application/json" \
-d @- <<EOF
{"chat_id": $CHAT_ID, "body": "Завтра +18, без осадков", "client_id": "forecast-2026-10-05"}
EOF
{
"message_id": 90230,
"duplicate": false,
"message": {
"id": 90230,
"chat_id": 812,
"sender_id": 41207,
"author": {"id": 41207, "display_name": "Погода на даче", "username": "dacha_weather_bot", "avatar_key": null, "avatar_url": null, "is_bot": true},
"seq": 5121,
"type": "text",
"body": "Завтра +18, без осадков",
"caption": null,
"created_at": "2026-10-05T07:00:00.412Z",
"media_url": null,
"object_key": null,
"media": null,
"attachments": [],
"edited_at": null,
"call_status": null,
"call_duration": null,
"reply_to_message_id": null,
"quote": null,
"views": 0,
"comment_count": 0,
"poll": null,
"forwarded_from_user_id": null,
"forwarded_from_chat_id": null,
"forwarded_from_name": null,
"about_user_id": null,
"about_name": null,
"reactions": [],
"duration_ms": null,
"file_name": null,
"file_size": null
},
"composed_at_ms": null
}
Повтор с тем же client_id
curl https://api.bot.marx.moscow/api/bot/v1/messages \
-H "Authorization: Bearer $MARX_TOKEN" \
-H "Content-Type: application/json" \
-d @- <<EOF
{"chat_id": $CHAT_ID, "body": "Завтра +18, без осадков", "client_id": "forecast-2026-10-05"}
EOF
{"message_id": 90230, "duplicate": true}
Опрос
curl https://api.bot.marx.moscow/api/bot/v1/messages \
-H "Authorization: Bearer $MARX_TOKEN" \
-H "Content-Type: application/json" \
-d @- <<EOF
{"chat_id": $CHAT_ID, "kind": "poll", "question": "Когда едем?", "options": ["Суббота", "Воскресенье"]}
EOF
{
"message_id": 90231,
"duplicate": false,
"message": {
"id": 90231,
"chat_id": 812,
"sender_id": 41207,
"author": {"id": 41207, "display_name": "Погода на даче", "username": "dacha_weather_bot", "avatar_key": null, "avatar_url": null, "is_bot": true},
"seq": 5122,
"type": "poll",
"body": "{\"question\": \"Когда едем?\", \"options\": [\"Суббота\", \"Воскресенье\"], \"closed\": false}",
"caption": null,
"created_at": "2026-10-05T07:00:02.035Z",
"media_url": null,
"object_key": null,
"media": null,
"attachments": [],
"edited_at": null,
"call_status": null,
"call_duration": null,
"reply_to_message_id": null,
"quote": null,
"views": 0,
"comment_count": 0,
"poll": {
"question": "Когда едем?",
"closed": false,
"my_vote": null,
"my_votes": [],
"total": 0,
"voters": 0,
"anonymous": true,
"multiple": false,
"revote": true,
"can_close": true,
"recent_voters": [],
"options": [{"label": "Суббота", "count": 0}, {"label": "Воскресенье", "count": 0}]
},
"forwarded_from_user_id": null,
"forwarded_from_chat_id": null,
"forwarded_from_name": null,
"about_user_id": null,
"about_name": null,
"reactions": [],
"duration_ms": null,
"file_name": null,
"file_size": null
},
"composed_at_ms": null
}
Ошибки
| Код | detail |
|---|---|
| 400 | an empty post says nothing, a poll needs a question and two options, a image post needs a media_id |
| 403 | this account cannot post here — у бота нет права писать в этот чат |
| 404 | chat not found — чата нет или бот в нём не состоит |
| 422 | not your attachment, unknown attachment — media_id загрузил не этот бот или его нет |
POST /media
Загрузить картинку, видео или файл, чтобы затем отправить его через POST /messages с media_id. Тело — multipart/form-data.
| Поле формы | Что это |
|---|---|
file | Файл, обязательно. Картинка до 50 МБ, видео до 320 МБ, файл до 50 МБ. Для image и video тип файла (Content-Type части) должен быть image/… или video/… |
kind | image (по умолчанию), video или file |
duration_ms | Для видео: длительность в миллисекундах |
poster | Для видео: кадр-обложка, картинка |
Ответ: media_id, size в байтах, width и height для картинки (иначе null). Отказ — 400 с причиной в detail, например not a readable image.
curl https://api.bot.marx.moscow/api/bot/v1/media \
-H "Authorization: Bearer $MARX_TOKEN" \
-F kind=image -F "file=@map.png;type=image/png"
{"media_id": 5521, "size": 183204, "width": 1280, "height": 720}
Затем:
{"chat_id": 812, "kind": "image", "media_id": 5521, "caption": "Карта осадков"}
POST /reactions
Поставить реакцию на сообщение в чате, где состоит бот. Тот же запрос второй раз снимает её.
| Поле запроса | Тип | Что это |
|---|---|---|
message_id | целое, обязательно | Номер сообщения |
emoji | строка, обязательно | Эмодзи, от 1 до 16 символов |
curl https://api.bot.marx.moscow/api/bot/v1/reactions \
-H "Authorization: Bearer $MARX_TOKEN" \
-H "Content-Type: application/json" \
-d @- <<EOF
{"message_id": $MESSAGE_ID, "emoji": "👍"}
EOF
{"ok": true}
Сообщения нет или бот не состоит в его чате — 404 message not found.
POST /channels
Канал, владелец которого — бот, с этим названием. Если у бота уже есть канал с таким названием, возвращается он, иначе создаётся новый. Людей в канал добавляют из приложения.
| Поле | Что это |
|---|---|
title | Запрос: название, от 1 до 128 символов |
id | Ответ: номер канала |
created | Ответ: true, если канал создан этим запросом |
curl https://api.bot.marx.moscow/api/bot/v1/channels \
-H "Authorization: Bearer $MARX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Погода на даче"}'
{"id": 1304, "title": "Погода на даче", "created": true}
GET /updates
Новые сообщения для бота. Как это устроено — в разделе Длинный опрос.
| Параметр | По умолчанию | Что это |
|---|---|---|
offset | 0 | Номер первого нужного обновления. Все обновления с меньшим update_id считаются полученными и удаляются |
limit | 100 | Сколько обновлений вернуть, от 1 до 100 |
timeout | 0 | Сколько секунд ждать, если обновлений нет, от 0 до 50 |
curl "https://api.bot.marx.moscow/api/bot/v1/updates?offset=0&timeout=30" \
-H "Authorization: Bearer $MARX_TOKEN"
[
{
"update_id": 7,
"chat": {"id": 812, "type": "group", "title": "Дача"},
"message": {
"id": 90229,
"chat_id": 812,
"sender_id": 40011,
"author": {"id": 40011, "display_name": "Анна", "username": "anna", "avatar_key": null, "avatar_url": null, "is_bot": false},
"seq": 5120,
"type": "text",
"body": "/today@dacha_weather_bot",
"caption": null,
"created_at": "2026-10-05T06:59:58.101Z",
"media_url": null,
"object_key": null,
"media": null,
"attachments": [],
"edited_at": null,
"call_status": null,
"call_duration": null,
"reply_to_message_id": null,
"quote": null,
"views": 0,
"comment_count": 0,
"poll": null,
"forwarded_from_user_id": null,
"forwarded_from_chat_id": null,
"forwarded_from_name": null,
"about_user_id": null,
"about_name": null,
"reactions": [],
"duration_ms": null,
"file_name": null,
"file_size": null
}
}
]
Задан вебхук — 409 webhook is set.
POST /webhook, DELETE /webhook
POST задаёт адрес, на который Marx отправляет каждое обновление; GET /updates после этого отвечает 409. DELETE снимает вебхук; неотправленные обновления остаются и приходят через GET /updates. Подробнее — Вебхук.
| Поле запроса | Что это |
|---|---|
url | Обязательно. Только https://, до 512 символов; адрес должен быть публичным |
secret | До 256 символов из A-Z, a-z, 0-9, _, -. Приходит в заголовке X-Marx-Bot-Secret каждого запроса |
curl https://api.bot.marx.moscow/api/bot/v1/webhook \
-H "Authorization: Bearer $MARX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://bot.example.org/marx", "secret": "Zr4q-8NnYtV2"}'
{"ok": true, "url": "https://bot.example.org/marx"}
curl -X DELETE https://api.bot.marx.moscow/api/bot/v1/webhook \
-H "Authorization: Bearer $MARX_TOKEN"
{"ok": true}
Адрес не принят — 400 с причиной: only https is allowed, the address is not public, the host does not resolve и другие.
PUT /commands, GET /commands, DELETE /commands
Список команд, который приложение показывает в меню чата с ботом. PUT заменяет весь список, DELETE очищает его. Правила — в разделе Команды.
curl -X PUT https://api.bot.marx.moscow/api/bot/v1/commands \
-H "Authorization: Bearer $MARX_TOKEN" \
-H "Content-Type: application/json" \
-d @- <<EOF
{"commands": [
{"command": "today", "description": "Погода на сегодня"},
{"command": "week", "description": "Прогноз на неделю"}
]}
EOF
{"commands": [{"command": "today", "description": "Погода на сегодня"}, {"command": "week", "description": "Прогноз на неделю"}]}
curl https://api.bot.marx.moscow/api/bot/v1/commands \
-H "Authorization: Bearer $MARX_TOKEN"
{"commands": [{"command": "today", "description": "Погода на сегодня"}, {"command": "week", "description": "Прогноз на неделю"}]}
curl -X DELETE https://api.bot.marx.moscow/api/bot/v1/commands \
-H "Authorization: Bearer $MARX_TOKEN"
Список не прошёл проверку — 400, в detail — какой элемент и что с ним, например commands[1].command: must match ^[a-z0-9_]{1,32}$, without the /. Токен человека, а не бота, — 403 this account is not a bot.