They are mutually exclusive. While a webhook is enabled, getUpdates returns 409. Use polling for development, webhook for production.
Overview
Pick one delivery mode. Polling actively pulls; webhook gets pushed. setWebhook and deleteWebhook are high-risk controlled operations — do not run them casually against a production bot.
getUpdates parameters
offset— when using a cursor, pass the highestupdate_idfrom the previous batch plus one.limit— 1 to 100, default 100.timeout— 0 to 50 seconds of long polling.allowed_updates— type filter, e.g.["message", "callback_query"].
A successful getUpdates consumes only the batch it returned. Persist the returned updates before further processing. Undelivered ordinary updates are kept for up to 24 hours. A callback_query can be delivered for up to 150 seconds, and the separate window for answerCallbackQuery is 300 seconds.
curl --silent --show-error "https://call.mp.net/bot/getUpdates" -X POST \
-H "Authorization: Bearer ${MPCHAT_BOT_TOKEN}" \
-H "Content-Type: application/json" \
--data '{"offset":0,"timeout":30,"limit":50,"allowed_updates":["message","callback_query"]}'
Configuring a webhook
curl --silent --show-error "https://call.mp.net/bot/setWebhook" -X POST \
-H "Authorization: Bearer ${MPCHAT_BOT_TOKEN}" \
-H "Content-Type: application/json" \
--data '{"url":"https://example.com/mp-bot/webhook","secret_token":"YOUR_WEBHOOK_SECRET","allowed_updates":["message","callback_query"]}'
url— required, must be HTTPS. An empty string is equivalent todeleteWebhook.secret_token— optional; when set, requests carry theX-MpChat-Bot-Api-Secret-Tokenheader.max_connections,allowed_updates— optional tuning and type filter.
Webhook URL changes preserve pending updates, retry state and deadlines. Use drop_pending_updates: true only to discard updates accepted before the switch. max_connections defaults to 40 (range 1–100) across service instances.
How allowed_updates works
Omit it to keep the previous filter.
Pass
[]to use the default set, which excludeschat_member,message_reaction, andmessage_reaction_count.Pass a non-empty list to receive the specified types, for example
["message", "callback_query"].
This applies to polling and webhook registration. Changes apply to new updates and do not retroactively filter the existing queue.
Webhook probes and delivery
The registration probe can be an empty JSON object ({}). When you configure secret_token, both the probe and real updates carry X-MpChat-Bot-Api-Secret-Token.
Verify the header first and return 2xx for an authenticated probe. For an update, persist it or enqueue it durably before returning 2xx. Failed deliveries can be retried. Deduplicate with update_id per bot so a repeat delivery does not repeat the business action.
Use the same secret value in registration and on the receiver. The handler below assumes a JSON parser and a durable queue with a unique key per bot and update ID.
async function handleWebhook(req, res) {
const secret = process.env.WEBHOOK_SECRET;
const incoming = req.headers["x-mpchat-bot-api-secret-token"];
if (!secret || incoming !== secret) return res.status(401).end();
const update = req.body;
if (!update || typeof update !== "object" || Array.isArray(update)) {
return res.status(400).end();
}
if (Object.keys(update).length === 0) return res.status(204).end();
if (!Number.isSafeInteger(update.update_id)) return res.status(400).end();
try {
await enqueueUpdateOnce(update);
return res.status(204).end();
} catch {
return res.status(503).end();
}
}
Choosing a mode
Local development: getUpdates; confirm no webhook with
getWebhookInfo.Production: webhook +
secret_tokenvalidation.Switching: verify in a test environment before running
setWebhookagainst the target bot.
Related
When supported group events are enabled, joins are represented as message.new_chat_members, leaves as message.left_chat_member, and pins as message.pinned_message when visible to the bot. Kafka-sourced group events and join-request actions are pre-release.
