SMeetMini Apps

SMeet Mini Apps

Author API reference

The reference below the first sections is generated from the machine-readable description of the API, which you can also download as openapi.json. Method names, JSON fields and error codes are the same in every language of this documentation.

Requests#

  • Base URL: https://messenger.scrile.com/mini-app-api/v1. A method is called as POST https://messenger.scrile.com/mini-app-api/v1/<method> with a JSON body in UTF-8 and Content-Type: application/json.
  • A body may be at most 64 KiB; a larger one is refused with 413 PAYLOAD_TOO_LARGE and limit in bytes before it is read.
  • A path that is not a method, or another HTTP method than POST, answers 400 INVALID_REQUEST.
  • The API answers no CORS requests and sets no cookies: it is for servers only.
  • An answer that SMeet's proxy gives itself, a 429 or a 413, has the same envelope with an empty request_id.

Authentication#

Every call carries the key of one environment of the Mini App:

HTTP
Authorization: Bearer smac1_<key id>_<secret>

The key decides the Mini App and the environment. A login code of another app or environment is refused (APP_MISMATCH, ENVIRONMENT_MISMATCH); a session of another app or environment is reported as not_found. Keys are issued and revoked on the Mini App's screen in My bots (Keys).

Limits#

WhatLimit
Calls with one key50 a second
Calls of one Mini App, all keys200 a second
All Mini Apps together1000 a second
Body64 KiB

Over a limit the answer is 429 RATE_LIMITED with retry_after; repeat the same request with the same key after it.

Generated from the contract SMeet Mini Apps author API 1.0.0 (OpenAPI 3.1.0). Base URL: https://messenger.scrile.com/mini-app-api/v1. Machine-readable: openapi.json.

The API the server of a Mini App calls to turn a login code into a session and to check and revoke sessions.

Methods#

Every method is called as POST https://messenger.scrile.com/mini-app-api/v1/<method> with a JSON body; there are no GET methods. Authentication: The key of one environment of the Mini App, shown once in "My bots" when it is issued. Keep it on the server only, never in the page, a link or a log. Each environment has up to two active keys, so a key can be replaced without a pause. A revoked or unknown key fails with 401 INVALID_CREDENTIALS.

MethodHTTPIdempotency-KeyDescription
SessionsSigning a person in and checking that they may still use the Mini App.
exchangeLaunchCodePOSTrequiredExchange a login code and its PKCE verifier for a Mini App session.
checkSessionPOSToptionalCheck a Mini App session now, before a protected operation.
revokeSessionPOSToptionalEnd a Mini App session, for example when the person signs out of your app.

exchangeLaunchCode#

POST /exchangeLaunchCodeSessions

Exchange a login code and its PKCE verifier for a Mini App session.

The code comes from authorize() in the page and lives 60 seconds; the verifier is the one the SDK made for it. Exchange it once: the same Idempotency-Key with the same body within 60 seconds of the exchange repeats the answer (a lost response), anything else with a used code fails with CODE_ALREADY_USED. A wrong verifier revokes the code. When the person may not use the Mini App any more, the answer is ACCESS_DENIED with the reason. The session lives 15 minutes at most; the page renews it with a new authorize() and a new exchange.

Headers#

HeaderTypeRequiredDescription
Idempotency-KeyIdempotencyKeyYesOne key per sign-in, for example bound to your login attempt (login:<attempt id>). Send the same key with the same body when you repeat the request after a timeout, 429 or 503.

Request body (JSON)#

FieldTypeRequired
codeLoginCodeYes
code_verifierCodeVerifierYes

Result#

The result field holds Session. The session and who signed in.

On failure the answer is an error object with a code from the table of error codes.

checkSession#

POST /checkSessionSessions

Check a Mini App session now, before a protected operation.

Call it without a cache before every operation that acts for the person: creating or changing their data, uploading or downloading a file, reading what belongs to them. Every state of the session is an answer 200: active: true with the current details, or active: false with the reason. An unknown token, a wrong secret and a session of another application or environment all give reason: not_found. During a pause of the platform the answer is active: false, reason: maintenance.

Headers#

HeaderTypeRequiredDescription
Idempotency-KeyIdempotencyKeyNoAccepted and not needed; the method changes nothing or is idempotent by itself.

Request body (JSON)#

FieldTypeRequired
session_tokenSessionTokenYes

Result#

The result field holds SessionCheck. The state of the session.

On failure the answer is an error object with a code from the table of error codes.

revokeSession#

POST /revokeSessionSessions

End a Mini App session, for example when the person signs out of your app.

Revokes only a session of the key's application and environment. The answer is the same for an unknown token, a wrong secret, a session of another application or environment and a session that is already revoked, and nothing changes then. Works during a pause of the platform too.

Headers#

HeaderTypeRequiredDescription
Idempotency-KeyIdempotencyKeyNoAccepted and not needed; the method changes nothing or is idempotent by itself.

Request body (JSON)#

FieldTypeRequired
session_tokenSessionTokenYes

Result#

Always the same answer. The result field holds an object with these fields.

FieldTypeRequiredDescription
revokedbooleanYesAlways true.

On failure the answer is an error object with a code from the table of error codes.

Types#

Simple types#

Strings with a fixed format. Fields refer to them by name.

NameTypeDescription
IdstringA decimal identifier passed as a string. Pattern: ^[0-9]{1,20}$. Example: 1000.
LoginCodestringA one-time login code from authorize(); it lives 60 seconds. Pattern: ^smlc_[A-Za-z0-9_-]{43}$.
CodeVerifierstringThe PKCE verifier (RFC 7636) that the SDK made for the code; SMeet checks it with S256. Pattern: ^[A-Za-z0-9._~-]{43,128}$.
SessionTokenstringA Mini App session. Your server keeps it; it never reaches the page. Pattern: ^smas1_([0-9a-f]{16})_([A-Za-z0-9_-]{43})$.
AuthorKeystringThe key of one environment of the Mini App, sent as Authorization: Bearer. Pattern: ^smac1_([0-9a-f]{16})_([A-Za-z0-9_-]{43})$.
IdempotencyKeystring1 to 128 characters. Pattern: ^[A-Za-z0-9._:-]{1,128}$.
Timestampstring (date-time)RFC 3339, UTC. Example: 2026-10-10T12:15:00Z.
RevisionstringThe revision of the person's conversation with the bot. Pass it to the Bot API as expected_access_revision; compare it only for equality. 1-64 characters. Example: 1088.
EnvironmentstringOne of: production, test.
SpaceKindstringSMeet's public space or an organisation. One of: public, organization.
LanguageCodestringThe language of the person's SMeet interface. One of: en, ru.
ScopestringWhat the person agreed to share beyond the id and the language; profile is the display name. One of: profile.
SessionReasonstringWhy a session is not active. Consumers must accept unknown values. One of: not_found, maintenance, expired, revoked, launch_closed, parent_session_revoked, operator_session, account_disabled, chat_stopped, membership_revoked, app_unavailable, space_disabled, bot_unavailable, test_access_removed, user_revoked, config_changed.
AccessDeniedReasonstringWhy an exchange is refused with ACCESS_DENIED. Consumers must accept unknown values. One of: launch_closed, parent_session_revoked, operator_session, account_disabled, chat_stopped, membership_revoked, app_unavailable, space_disabled, bot_unavailable, test_access_removed, user_revoked, config_changed.

App#

The Mini App the key belongs to.

FieldTypeRequiredDescription
idIdYes
bot_idstring or nullYesThe bot's id, the same as id of getMe in the Bot API.
titlestring or nullYesThe title of the configuration the person opened.

Space#

Where the person opened the Mini App.

FieldTypeRequired
idIdYes
kindSpaceKindYes

User#

The person who signed in.

FieldTypeRequiredDescription
idIdYesThe same id the bot sees as from.id in the Bot API.
display_namestringNoPresent only when the Mini App asks for profile and the person agreed.
language_codeLanguageCodeYes

Chat#

The person's private chat with the bot.

FieldTypeRequiredDescription
idIdYesUse it as chat_id in the Bot API.
typestringYesAlways private.
access_revisionRevisionYes

Session#

A new Mini App session and who it is for.

FieldTypeRequiredDescription
session_tokenSessionTokenYes
expires_atTimestampYes15 minutes after the exchange at most, and never after the person's SMeet sign-in ends.
environmentEnvironmentYes
appAppYes
spaceSpaceYes
userUserYes
chatChatYes
scopesarray of ScopeYesWhat the person agreed to share; empty when the Mini App asks only for the id and the language.
start_paramstring or nullYesThe parameter of the button or the link that opened the Mini App; null when there was none. Pattern: ^[A-Za-z0-9_-]{0,64}$.

SessionCheck#

The state of a session. active: false comes with reason only; active: true with the session's details, read now: chat.access_revision is the revision to put into what you send the person after this check.

FieldTypeRequiredDescription
activebooleanYes
reasonSessionReasonNoPresent when active is false.
expires_atTimestampNoPresent when active is true.
environmentEnvironmentNo
appAppNo
spaceSpaceNo
userUserNo
chatChatNo

Errors#

Any failure. See ErrorCode for the meaning of each code and the HTTP status it comes with. The Retry-After header is set whenever the body carries retry_after. A 502, 503 or 504 without this JSON body comes from a proxy in front of SMeet: treat it as TEMPORARILY_UNAVAILABLE.

Headers of an error answer: Retry-After, X-Request-Id, WWW-Authenticate.

Error object#

Every failed call answers with this envelope and a matching HTTP status.

FieldTypeRequiredDescription
okbooleanYesAlways false.
errorErrorYes
request_idstringYesQuote it when you write to support. Empty when the proxy in front of SMeet answered.

The error field:

FieldTypeRequiredDescription
codeErrorCodeYes
messagestringYesHuman-readable, English, free of secrets. Do not parse it.
retry_afterintegerNoSeconds to wait before retrying. Present only when a retry makes sense. At least 1.
reasonstringNoWith ACCESS_DENIED, a value of AccessDeniedReason; with CODE_ALREADY_USED, replay_unavailable when a repeat of the exchange cannot be answered any more.
fieldstringNoPresent with INVALID_REQUEST, the field at fault (code, code_verifier, session_token, idempotency_key, body, or method for a path that is no method).
limitintegerNoPresent with PAYLOAD_TOO_LARGE, the largest accepted body in bytes.

Error codes#

CodeHTTPMeaning
INVALID_CREDENTIALS401The key is missing, unknown or revoked. Do not retry
INVALID_REQUEST400A field is missing or malformed; field names it
PAYLOAD_TOO_LARGE413The body is larger than 64 KiB; limit gives the size in bytes
RATE_LIMITED429Too many requests; wait retry_after and repeat with the same key
MINI_APPS_MAINTENANCE503Mini Apps are paused; exchangeLaunchCode only, retry_after 30
TEMPORARILY_UNAVAILABLE503Nothing was changed; repeat the same request with the same key after retry_after
IDEMPOTENCY_KEY_REQUIRED400exchangeLaunchCode needs an Idempotency-Key header
IDEMPOTENCY_CONFLICT409The key was used for this code with another code_verifier
APP_MISMATCH403The code belongs to another Mini App than the key
ENVIRONMENT_MISMATCH403The code belongs to the other environment of the key's Mini App
CODE_NOT_FOUND400No such code. The page signs in again
CODE_EXPIRED400The code lived its 60 seconds. The page signs in again
CODE_REVOKED400The code was revoked: the window closed, access ended, or a wrong verifier was sent. The page signs in again
CODE_ALREADY_USED400The code was exchanged already; with reason replay_unavailable a repeat cannot be answered any more. The page signs in again
CODE_VERIFIER_MISMATCH400The verifier does not match the code, and the code is revoked now. The page signs in again
ACCESS_DENIED403The person may not use the Mini App now; reason says why