Receiving updates
Everything that happens in the bot's chats arrives as an Update: a new message, an edit, a reaction, a button press. The bot's own messages are not reported.
Updates wait in a queue in the bot's volume until you confirm them. You get them in one of two ways: long polling (the default) or a webhook.
Update types
type | Field | When |
|---|---|---|
message | message | A new message: text, a file (download it with GET …/file), a poll. |
edited | message | Someone edited their message. |
deleted | deleted | A message was deleted for everyone. |
reaction | reaction | A reaction was set; an empty emoji means it was removed. |
poll | message | Votes in a poll changed or the poll was closed. |
chat | chat | A new chat, a chat request, a group invitation; the group's title, members or disappearing-messages timer changed. |
notice | notice | A system line in the chat, see notice codes. |
expired | expired | Disappearing messages were erased (an array of message ids). |
button | button | Someone pressed a button with data. See buttons. |
Commands are ordinary message updates whose text starts with /.
Long polling
GET /v1/updates?offset=<last id + 1>&timeout=30&limit=100timeout— wait up to this many seconds (at most 60) if the queue is empty.offset— confirms and removes every update with a smaller id. Pass the last id you processed plus one.limit— at most this many updates (1–100, default 100).
The answer is a JSON array, possibly empty. If you crash before confirming, the same updates come again, so make your handling idempotent by id.
Webhook
Set WEBHOOK_URL (and WEBHOOK_SECRET) and the gateway POSTs every update to it, one JSON Update per request, strictly in order. GET /v1/updates then answers 409.
- A 2xx answer means delivered.
- Anything else, or no answer, is retried after 1 s, 2 s, 4 s … up to 5 minutes between attempts. The next update waits until this one is delivered.
- The
X-Mailbees-Signatureheader issha256=<hex HMAC-SHA256 of the body with WEBHOOK_SECRET>. Check it before trusting the body.
import hashlib, hmac
def verify(body: bytes, header: str, secret: str) -> bool:
want = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(want, header or "")import { createHmac, timingSafeEqual } from 'node:crypto'
function verify(body, header, secret) {
const want = Buffer.from('sha256=' + createHmac('sha256', secret).update(body).digest('hex'))
const got = Buffer.from(header ?? '')
return got.length === want.length && timingSafeEqual(got, want)
}func verify(body []byte, header, secret string) bool {
m := hmac.New(sha256.New, []byte(secret))
m.Write(body)
return hmac.Equal([]byte(header), []byte("sha256="+hex.EncodeToString(m.Sum(nil))))
}Answer quickly and do slow work in the background: while you hold the request, the next updates wait.
Read receipts
Until the bot marks messages read, people see them as "delivered". Mark them with POST /v1/chats/{chat}/read. The countdown of disappearing messages starts for the bot from that moment too.