Skip to main content

Bot and MiniApp development FAQ

Quick answers to common MPChat bot and MiniApp questions: getting a chat_id, fixing 409, file_id reuse, 429 handling, and which methods are unsafe to test.

In this guide, DocOnly and L0–L3 describe testing precautions and operation risks, not whether an API method is supported. Check official support status separately; verify targets and recovery steps before changing messages, chats, or delivery settings.

Quick answers to the questions developers hit first. For parameter-level details, see core.mp.net/bots.


Overview

Common questions grouped by topic. If your issue is not here, check the relevant guide in this collection.

Getting started

Messaging

  • Why can't the bot DM first? A user must establish context; sendMessage needs a valid chat_id.

  • How do I get a chat_id? Have the user message the bot, then read message.chat.id from the Webhook update or getUpdates, depending on your configured delivery mode.

  • getUpdates returns []? No message yet, or the batch was consumed. Check offset and webhook state.

  • getUpdates returns 409? A webhook is enabled (mutually exclusive). Confirm with getWebhookInfo; do not run deleteWebhook yourself.

Media and limits

  • Can I reuse a file_id? No. Use a public URL or multipart.

  • Does banChatMember kick? No — it mutes (restricted). Lift with unbanChatMember. L3 DocOnly.

  • Why are sendPoll / sendLocation unavailable? They currently return 501.

  • Got a 429? Stay at or below 30 req/s and add exponential backoff.

MiniApp

  • Can frontend data log a user in directly? No. The backend must verify the initData signature; initDataUnsafe is UI only.

  • Is shortName the same as miniapp id? No. shortName is the human slug in https://mp.net/{bot}/{shortName}; miniapp_id (ma_…) is the platform id inside signed initData.

  • How do I open a specific MiniApp screen? Append ?startapp=…; it becomes signed initData.start_param.

  • How do I disable the link preview card? On sendMessage, link_preview_options.is_disabled=true turns off previews for both ordinary URLs and MiniApp links.

Safety

  • Which methods are unsafe to test? DocOnly: logOut, leaveChat, deleteMessage(s), banChatMember, setWebhook, deleteWebhook.

  • Where is the official reference? core.mp.net/bots — parameter-level source of truth.

Why does an existing private chat return HTTP 403?

  • If the user blocks the bot, sending, forwarding, or copying a message into that private chat returns HTTP 403. Skip retries for this error. The bot can send new messages after the user unblocks it. Blocked messages are not resent automatically.

What does a retry or an empty queue mean?

  • Webhook retries keep the original update_id. After validating the request, persist the update with a unique key scoped to the bot and update_id before returning HTTP 2xx (for example, 200 or 204). Make business actions idempotent as well, so processing a job again cannot duplicate a reply or a state change.

  • Ordinary updates can be delivered for up to 24 hours. Callback updates have up to 150 seconds for delivery, with a separate 300-second window for answerCallbackQuery.

  • pending_update_count=0 means no updates are currently pending. Check getWebhookInfo for recent delivery errors and compare with your own receipt and processing logs to confirm what reached your service.

Why does the callback button keep spinning?

  • Confirm the button uses callback_data. If you filter allowed_updates, include callback_query. Check whether the update reached your service within the 150-second delivery window.

  • Call answerCallbackQuery promptly with callback_query.id within 300 seconds of the button press. Only the first accepted answer for the same ID succeeds. A repeated or expired answer returns HTTP 400.

  • The client does not display the answer’s text or show_alert. To give visible feedback, edit the message or send a reply.

Why does the MiniApp button work only in private chat?

  • Ordinary web_app buttons are private-chat only. For MiniApp sharing in a group or supergroup the bot has joined, the sendMessage inline keyboard must have exactly one row and one button containing only text and web_app. Check that the URL belongs to an enabled MiniApp owned by this bot.

Why did the keyboard or media caption disappear after an edit?

  • Composite message edits clear the inline keyboard or media caption when the corresponding field is omitted. To preserve either field, include its current value in the edit. Use the dedicated edit method when updating only the keyboard or only the caption.

Related

This FAQ summarizes behavior that may change. Always confirm current status on the official methods page.

Did this answer your question?