Skip to content

Lobby ​

GET /v1/lobby tells the game client, in one request, what Play will start for the current player: the display mode, the project's game, the next level, an unfinished run, and the result of the last run. The server decides all of it — the embed snippet on your site does not change, and the browser never decides progress or rewards.

Keyboard navigation ​

Use Tab to enter the iframe and reach Play, settings or the daily-wheel button. Enter and Space activate those controls. Match3 and Memory expose a card/cell grid: arrow keys move focus; Enter or Space sends the corresponding semantic game action. Parcel exposes a flight control for launch and flaps. Escape opens the pause menu; menu and result buttons use the same keyboard activation. Controls respect each mechanic's pending and pause states; Memory can buffer one additional flip as described in game runs. The server still determines every result, level and reward.

Safari on Mac can require Option+Tab to reach buttons when keyboard navigation is disabled in its settings. Use Shift+Option+Tab to move backwards in that mode. Apple's Safari guide explains the keyboard-navigation setting.

Display modes ​

entry_modeProject settingplay blockStarting a run
lobbyplay_mechanic is setpresentPOST /v1/game-runs starts the game in play.mechanic
legacyplay_mechanic is emptyabsent (wheel too)The active template's own flow
wheel_onlySite wheel; saving requires a ready wheel client and a published site tableabsent409 mechanic_not_enabled

Projects that ran match3_v1 as their active template were given play_mechanic = "match3_v1" automatically. play_mechanic is set with PATCH /v1/admin/projects/{id}; the API reference lists the checks it runs.

GET /v1/lobby ​

  • Auth: the player's session token (Authorization: Bearer); anonymous sessions only in free_play.
  • The call does not change progress or claims; exceeding its limit records a rate_exceeded fraud flag. Responses use Cache-Control: no-store; the size budget is 8 KiB (the server logs a warning if exceeded).
  • Limit: 60 requests per minute per player.

Example response:

json
{
  "assets": {
    "lobby_background": null
  },
  "config_revision": 1,
  "entry_mode": "lobby",
  "last_result": {
    "level_number": 1,
    "mechanic": "match3_v1",
    "reward": {
      "status": "pending"
    },
    "run_id": "00000000-0000-0000-0000-000000000007",
    "status": "won"
  },
  "play": {
    "active_run": null,
    "available": true,
    "levels_total": 15,
    "mechanic": "match3_v1",
    "next_level": {
      "cycle_round": null,
      "id": "score_intro",
      "number": 2,
      "preview": {
        "goals": [
          {
            "target": 1000,
            "type": "score"
          }
        ],
        "moves": 12,
        "tier": "intro"
      }
    },
    "title": "Ночной рынок",
    "track_complete": false,
    "unavailable_reason": null
  },
  "schema": 1,
  "server_time": "2026-10-01T12:00:00.123Z",
  "theme": {
    "accent": "#d79a3c"
  },
  "viewport": {
    "height": 760,
    "width": 420
  },
  "wheel": {
    "enabled": false,
    "entitlement": null,
    "pending": null,
    "version": null,
    "wheel_id": null
  }
}
FieldMeaning
schemaVersion of this response shape — not the same as config_revision
config_revisionGrows on every change of the project's game settings; compare it to notice changes
entry_modeSee display modes
server_timeServer clock at response time; base countdowns on it
viewportLogical size of the game area (420×760)
theme.accentAlways a lowercase #rrggbb string. The project's brand color if set with at least 3:1 contrast against #0a1226; otherwise the game's accent. The default primary color #6c5ce7 counts as not set
assets.lobby_backgroundA normalized WebP copy840×1520, up to220 KiB, with a service URL and dimensions; null if absent or uploaded before normalization
play.mechanic, play.titleThe game behind Play and its player-facing title
play.available, play.unavailable_reasonfalse with not_built, disabled, plan_limit or unsupported_version — show the game as temporarily unavailable
play.next_levelnumber, id, cycle_round и серверное preview: цели и ходы, для уровней Match3 v2 также tier и при введении элемента new_element. Поле и seed не передаются
play.levels_total, play.track_completeTrack size, and whether every level is completed
play.active_runThe player's unfinished, not expired run of this game; resumable: false means it cannot be continued after a reload
last_resultThe player's last won or lost game run, excluding wheel outcomes, with reward.status when the run has a reward claim
wheelAn enabled wheel includes wheel_id (daily or site), published version, entitlement and an unrevealed pending result when present. A disabled wheel has enabled: false and null summary fields; its wheel_id is null in lobby mode and "site" in wheel_only mode

What the player sees ​

The lobby displays Play with the next server-selected level, Continue for an active resumable run, or Play for a run that must be closed before restarting. A run without a level number has no numeric subtitle. A completed track without a next level shows “Все уровни пройдены”. An unavailable mechanic shows a neutral card without exposing internal plan restrictions. Offline mode disables Play and preserves only previously confirmed information.

An enabled daily wheel opens in a sheet over the lobby. wheel_only opens the site wheel directly, without Play or a game engine. Rights and countdowns come from the server; the full wheel view supplies the published ticket_cost used to decide whether the ticket balance can pay for a spin. Changing to wheel_only prevents new game starts; reads and commands for previously created game runs still follow those runs' own mechanics.

Settings control sound and reduced motion. The widget refreshes lobby state when the network returns, when the tab becomes visible, on a persisted pageshow, and when returning from an activity. Failed loads retry after 5, 15, 30 and then 60 seconds while online and visible. The lobby_shown parent event is emitted after the lobby becomes ready, only to the handshake origin listed in allowed_parent_origins.

From the lobby to a run ​

  • Play: POST /v1/game-runs with a fresh start_id, intent: "next", expected_mechanic: play.mechanic and the rule versions your client supports. If play.active_run is present, the same call returns that run with resumed: true.
  • Continue after a reload: GET /v1/game-runs/{play.active_run.run_id}.
  • 409 mechanic_changed: the project switched games; the body carries the new play block and config_revision. Load that game and retry once with a new start_id and expected_mechanic; if it happens again, re-read the lobby.
  • 409 client_outdated: reload the page. 409 level_locked: re-read the lobby. 503 mechanic_unavailable and 402 plan_limit_exceeded: show the game as temporarily unavailable, without automatic retries.
  • 429 rate_limited: the start created nothing; do not repeat it automatically.

All codes: Game runs → Errors.

The shared transition controller covers Play with an accent-colored medallion and a level card. It shows “Готовим поле…” after one second and “Подождать / В лобби” after ten seconds. Returning to the lobby leaves an in-flight start request running; a late successful response refreshes the lobby so the player can continue the run. A return with no confirmed lobby response hides the level number and disables Play until fresh state arrives.

The shared result window uses server scores, stars and progress. A restored result has no celebration. Reward status is fetched at opening and, while pending or checking, at 1, 2, 4, 8, 23 and 38 seconds; updates stop at 60 seconds or when the window closes. A network error says the reward will be checked when connectivity returns. The run_finished parent event carries mechanic and status, only to the approved handshake origin. Match3 использует общий MechanicModule, переходы и окно результата. Клиент поддерживает версии правил [1, 2]; прежние партии v1 восстанавливаются с их серверными целями и результатом.

Лобби загружает фон и эмблему только активного мира. lobby.background имеет приоритет над его стандартным фоном; фон механики из верхнего блока оформления используется отдельно при открытии игры. При скрытии лобби изображения и декоративные canvas освобождаются и восстанавливаются при возврате.

Memory использует атласы лиц и карточек, Parcel Pilot — слои небесного мира, колесо — собственный набор фона, обода и смысловых значков. Эти изображения загружаются при открытии соответствующего экрана. Подписи, доступные кнопки, правила и награды берутся из прежних контрактов; декоративные сундук и подарок не меняют вид награды. Окно результата загружается отдельным модулем при завершении партии. Ошибка загрузки предлагает обновить страницу, а закрытие виджета не создаёт запоздалое окно.

После 15-го уровня Match3 повторяет позиции 11–15. play.next_level.cycle_round описывает следующий старт; в текущей партии её круг берётся из сохранённого level.cycle_round. Лобби и карточка запуска показывают, например, «Уровень 13 · круг 2». preview.tier задаёт отметку сложности, а preview.new_element — отметку нового элемента (rocket, bomb, chain, ice, hole или sphere); браузер не определяет их по номеру уровня.

Noticing configuration changes ​

config_revision grows whenever the project's game settings change. A client that keeps the lobby open re-reads GET /v1/lobby (for example when the tab becomes visible again) and compares. A start with a stale expected_mechanic gets 409 mechanic_changed and creates no run. Runs started before a switch can still be finished: commands and reads follow the run's own game. The lobby of the new game does not show them as active_run; they close on expiry.

The current lobby document uses the same wasm CSP profile for Match3, Memory and Parcel Pilot. Switching between these games does not require weakening its policy or replacing the iframe. A change that requires a different document profile asks the player to reload; JavaScript cannot change an HTTP CSP header on the already open document. Wheel-only and the legacy entry use base.

After the single permitted retry, a second mechanic_changed returns to refreshed lobby state. It does not cause a third start request. Continuing an existing resumable run reads its run_id instead of silently creating another attempt.

Progress and identity ​

  • Level progress lives on the server, per project, player (external_user_id) and game. Switching the project's game does not reset it.
  • Anonymous players (free_play) are identified by an anonymous id the loader keeps in your site's localStorage. Clearing site data or switching devices starts again at level 1, and anonymous progress is not merged into an identified user.

Analytics ​

The game-run path records server events: game.started, game.game_won, game.game_lost and game.abandoned (with end_reason). They come from the server's own transactions, not from the browser.

Not a reward channel ​

Nothing in the lobby response grants a reward. Rewards are confirmed only by the signed webhook; the player-facing status is GET /v1/game-runs/{run_id}/reward. Общее лобби отображается при entry_mode: "lobby"; Match3 запускается через общие переходы и окно результата. В цикле is_replay: true исключает промо-награды.

Internal & integration documentation