SMeet Bot API
Mini Apps
A Mini App is a web page of the bot's author that opens inside SMeet, in a window over the chat with the bot. The bot opens it with a button, and a form the person sends from it reaches the bot as an update in the same queue as messages.
What a Mini App is#
A bot can have one Mini App. Its owner creates it in My bots (SMeet BotFather opens the screen), gives it a production and a test address on their own HTTPS server, and sends it for review; only the reviewed configuration runs in production. Before every launch SMeet shows the person who made the Mini App and what it will receive, and before every form it sends to the bot SMeet asks the person to confirm.
The page and its server are the author's. The bot's program does not have to serve them: it receives what the person sent and answers in the chat, as with any message.
The page, the person's sign-in, the author's server and publishing are described in the SMeet Mini Apps documentation: SDK, Sign-in, Your server and Publishing. This page covers what the bot sees.
getMe says whether this server runs Mini Apps and describes the bot's own:
{
"capabilities": ["chat_context", "access_revisions", "message_revisions", "initiator_conditions",
"strict_conditions", "mini_apps"],
"mini_app": {"id": "1000", "status": "active", "published": true}
}mini_appsincapabilitiesmeans themini_appbutton and themini_app_submissionupdate work on this server now. When it is missing (an older server, or Mini Apps switched off on the platform), send the same text without the button.mini_appis present while the bot has a Mini App.statusisactive,paused_by_ownerorblocked_by_admin;publishedsays whether a reviewed configuration is live.idis theapp_idof the bot's submissions.
The mini_app button#
A button with mini_app opens the bot's Mini App instead of sending a press to the bot:
{
"chat_id": "70051",
"text": "Fill in the request form. It opens in SMeet: press the button below.",
"reply_markup": {
"inline_keyboard": [
[{"text": "Open the form", "mini_app": {"start_param": "vpn-access"}}],
[{"text": "Help", "callback_data": "help"}]
]
}
}- A button has exactly one of
callback_data,urlandmini_app.mini_appis an object;start_paramis optional, up to 64 characters ofA-Z a-z 0-9 _ -, and is handed to the Mini App when it opens. Empty means no parameter. - Only in a private chat of a bot that has a Mini App, and not a deleted one. In a group, topic or channel, or from a bot without a Mini App, sendMessage, editMessageText, sendPhoto and sendDocument answer
400 INVALID_REQUESTwith"field": "reply_markup"and"reason": "mini_app_not_configured". A wrongstart_paramgetsINVALID_REQUESTwith"field": "reply_markup"and noreason. - The button opens the published configuration only. While there is none, or while the Mini App is paused or blocked, the person sees that it is not available; the button stays in the chat.
- The bot is not told about a press. The result of the call shows the button back as you wrote it, except that an empty
start_paramcomes back as nostart_param. - Apps without Mini App support (SMeet for Android, the desktop app and older versions of the web app and of SMeet for iOS) show the button inactive and explain nothing. Say in the text where the form opens, as in the example.
A link to the Mini App#
The same window opens from a link to the bot's profile with startapp: https://messenger.scrile.com/u/<bot_username>?startapp=<param>, where param follows the rule of start_param and may be empty. A person who opens the link without the bot started is offered to start it and open the Mini App in one step.
The mini_app_submission update#
When a person confirms a form, the bot receives:
{
"update_id": "4380",
"event_id": "2c7a1e94-3b6f-4d1a-8e2b-6f0c9d3a5b17",
"type": "mini_app_submission",
"date": "2026-10-10T12:00:00Z",
"mini_app_submission": {
"id": "6f1c9a2e-8a8f-4d6b-9a4e-6d2f0a3b7c11",
"app_id": "1000",
"environment": "production",
"client_request_id": "f3b0c9e2-form-1",
"from": {"id": "103", "display_name": "Dmitry", "username": "dmitry", "is_bot": false},
"chat": {"id": "5501", "type": "private", "access_revision": "1088"},
"data": {"subject": "VPN", "priority": "high"},
"date": "2026-10-10T12:00:00Z"
}
}- SMeet fixes
app_id,environment,fromandchat: the page cannot choose them.from.idis the same person asfrom.idof their messages, andchat.idis your private chat with them. datais the form exactly as the page sent it: a JSON object of up to 16 KiB. Check it as you check any input from people.- One submission is one update. The page names each form with a
requestId, which arrives asclient_request_id; when the page sends the same form again (after a network error, a reload, a second window), SMeet gives back the same submission and writes no second update. Deduplicate your own work byevent_id, as for every update (Deduplication). idis the submission as the person's app and the Mini App know it.- Submissions arrive through getUpdates or your webhook in queue order, with the same confirmation, FAILED list and 7-day retention as every update (Receiving updates).
Answering the person#
Answer in chat.id. The submission's chat.access_revision is the revision of the conversation when the person opened the Mini App; pass it as expected_access_revision, and build the key from the update:
POST /bot-api/v1/sendMessage HTTP/1.1
Host: messenger.scrile.com
Authorization: Bearer sbt1_EXAMPLE_REPLACE_WITH_YOUR_TOKEN
Idempotency-Key: 2c7a1e94-3b6f-4d1a-8e2b-6f0c9d3a5b17:reply
Content-Type: application/json
{"chat_id": "5501", "text": "Request SM-1042 is created. We will answer here.",
"expected_access_revision": "1088"}403 BOT_STOPPED_OR_BLOCKED: the person stopped or blocked the bot.409 ACCESS_REVISION_CONFLICT: the conversation changed since the form was sent (Stop and Start again, for example). Both are final for this answer: do not retry it, and if the work matters, wait for the person to come back (Conditional requests).- A server without
access_revisionsincapabilitiesdoes not check the condition: an older server skips the parameter and does the action without it, and a 1.2.0 server with conditions switched off refuses the call with400 INVALID_REQUESTand"field": "expected_access_revision". Send the condition only when the capability is listed (Capabilities, rule 1). - The person may have revoked the Mini App's access from its menu. Submissions the bot has not received yet are then cancelled, and the conversation itself stays: the bot may still answer what it has received.
When a submission is cancelled#
A submission that has not reached the bot is cancelled, and a long polling program sees it in skipped with the reason cancelled, when:
| What happened | Cancelled |
|---|---|
| The person stopped or blocked the bot, or left the bot's space | As every update of that chat |
| The person chose Revoke access in the Mini App's menu | Pending and FAILED submissions of that conversation |
| The owner deleted the Mini App | Pending and FAILED submissions of the Mini App |
| The platform blocked the Mini App or all Mini Apps of its owner | Pending and FAILED submissions of the Mini App |
| The organisation switched bots off | Every pending and FAILED update of the bot, at once (Operations) |
| The organisation switched Mini Apps off | When SMeet is about to hand the submission over |
| A test submission whose sender is no longer the owner, an accepted tester or a reviewer | When SMeet is about to hand the submission over |
The same checks run when the owner retries a FAILED submission: one that may no longer reach the bot is cancelled instead of replayed. A pause by the owner, a technical pause of the platform, a closed window and an expired login of the page cancel nothing; the submission waits in the queue as other updates do.
What the person sees#
The Mini App's page can ask SMeet where its submission stands:
| Status | Means |
|---|---|
pending | In the bot's queue, not confirmed yet |
delivered | The bot confirmed it: a long polling offset past it, or a 2xx of your webhook |
failed | It is in the owner's FAILED list |
cancelled | It was cancelled before delivery, or the owner skipped it |
expired | It was not confirmed within 7 days, or it is older than that |
So confirm a submission only once it is stored on your side: the page may tell the person "delivered" from then on.
The test environment#
"environment": "test" comes from the test address of the Mini App, which only the owner, testers who accepted an invitation and the reviewers of an open review can open. Production and test never share a submission, even with the same requestId. Keep test submissions out of your real work: a test form should not create a real request.