Receiving messages

Every message the bot is to get becomes an update. The bot either fetches its updates (long polling) or gets them posted to its address (webhook), one or the other.

Long polling

The bot calls GET /updates in a loop:

  1. The first request: offset=0&timeout=30.
  2. If there are updates, the answer comes at once. If not, the server holds the request for up to 30 seconds and answers as soon as an update appears, or with an empty array [] when the time is up.
  3. Having handled the updates, the bot passes offset = the highest update_id received + 1 in the next request. The server deletes the updates below it.

Until the bot passes an offset above an update's id, that update comes in every answer again: a bot that crashed gets what it had not handled after a restart. Updates are kept for 24 hours. A bot's update_ids grow without gaps in the order the messages appeared.

Keep one poll per bot. The HTTP client must wait longer than timeout: with timeout=30, at least 40 seconds.

Webhook

After POST /webhook Marx posts every update to the address set:

POST /marx HTTP/1.1
Host: bot.example.org
Content-Type: application/json
User-Agent: marx-bot-webhook
X-Marx-Bot-Secret: Zr4q-8NnYtV2

{"update_id": 7, "chat": {"id": 812, "type": "group", "title": "Dacha"}, "message": {…}}

DELETE /webhook returns the bot to long polling; updates not yet posted stay and come through GET /updates.

Update

FieldMeaning
update_idThe update's id for this bot
chat.idChat id: the chat_id to reply to
chat.typedirect or group
chat.titleThe group's title
messageThe message

Message

The same object the app gets about a new message. A full example is in the answer of GET /updates. The fields a bot needs:

FieldMeaning
idMessage id: the message_id for POST /reactions
chat_idChat id
sender_idThe sender's account id
authorThe sender: id, display_name, username (may be null), avatar_url, is_bot
typetext, image, video, file, voice, poll and others
bodyThe message text; for a poll, its description in JSON
captionCaption of a picture, video or file
created_atWhen it was sent, ISO 8601 in UTC
media_url, media, attachmentsAttachments: the file's address and description
file_name, file_size, duration_msFile name and size, length of a video or voice message
reply_to_message_id, quoteThe message this one replies to, and its quote
pollA poll: question, options, votes
forwarded_from_user_id, forwarded_from_chat_id, forwarded_from_nameWhere it was forwarded from

The other fields are for the app's display and are usually empty in messages to a bot. New fields may appear: do not reject an answer with an unknown field.

What a bot sees

ChatWhat the bot gets
Direct, with a personEvery message of the person
GroupMessages that start with a command: /command or /command@this_bot (but not /command@another_bot); messages that mention the bot, @bot_username; replies to this bot's messages
ChannelNothing: in a channel a bot only publishes

Never delivered: the bot's own messages, messages of other bots, the chat's service lines (a member joined, the chat was renamed). A bot does not see a group's ordinary conversation.

Commands

A command is a message that starts with /: /today, /today@dacha_weather_bot, /today Moscow. In a group with several bots, the name after @ says which bot it is for.

The app shows the command list with descriptions in the menu of a chat with the bot. It is set with PUT /commands or with /setcommands at @marxbot.

Parsing a command is up to the bot's program: the update carries the message text as it is.