webstation-broker
REST API

API overview

Where the endpoints live, how they are authenticated, and which ones RomM calls versus the room UI.

Every endpoint lives under the SUBFOLDER prefix, so with the default the API root is /streaming/api/. The examples on these pages talk to a container directly on its HTTP port (3000); behind a reverse proxy substitute RomM's origin.

Authentication

BROKER_SECRET is a shared secret between RomM and the container, like a password only the two of them know. When it's set, the lifecycle endpoints require it in the X-Broker-Secret header (an extra field sent along with the request) and answer 403 if that check fails. Leaving it unset is not a "no auth" mode: the broker refuses to start at all, unless dev mode (BROKER_DEV_MODE=true) is also set. In dev mode it does start with BROKER_SECRET unset, but then every session-lifecycle endpoint is left unauthenticated, so a dev-mode broker should never be exposed beyond local development.

Endpoints fall into five groups:

GroupCallerAuth
Lifecycle: activate, join, swap-discRomM's backendX-Broker-Secret
State and archive transfer: save-state, load-state, state-file, state-screenshot, imports, import-spec, exports, memory card, RetroArch core listRomM's backendX-Broker-Secret
Host actions: invite, exitthe room UI (invite), RomM (exit)the controller token as ?token=; exit also accepts the secret
Room: context, the collab websocketthe room UIa personal token, or an invite token, in the URL
Status and healthRomM's backend (status), anyone (health)X-Broker-Secret for status; none for health

The room UI never holds the secret. Its invite tile carries the controller token instead; exit accepts either so RomM and the controller token both work.

Endpoints

MethodPathPage
POST/api/session/activateLaunch a game
POST/api/session/swap-discLaunch a game
POST/api/session/joinUsers and invites
POST/api/session/inviteUsers and invites
GET/api/session/contextUsers and invites
POST/api/session/save-stateSave states
POST/api/session/load-stateSave states
GET / PUT/api/session/state-fileSave states
GET/api/session/state-screenshotSave states
POST/api/session/exitExit
PUT/api/session/imports/{name}.zipSave archives
GET/api/session/import-specDeclared imports
GET / DELETE/api/session/exports[/{name}.zip]Save archives
GET / PUT/api/session/memory-cardSave archives
GET/api/retroarch/coresRetroArch core manifest
GET/api/session/statusStatus
GET/api/healthStatus

The request and response models are documented in the Python reference, and a running broker serves its own OpenAPI schema at <SUBFOLDER>/openapi.json with the interactive explorer at <SUBFOLDER>/docs.

Conventions

  • Status codes carry meaning. 409 is "there is no session" (or "there already is one" on activate). 400 is "the running emulator cannot do that", for example a state route on an emulator without save states. 413 is a body over a configured ceiling. 422 is a payload the broker could not act on.
  • A "failed" status is a real answer, not an error. Save and load report failed when the emulator did not acknowledge, or the slot held no state.
  • Slots resolve to the emulator's working slot. RomM is the library of states, so each emulator works in exactly one slot and echoes the slot it actually used. Whatever slot a request names, the response says which one it landed in.

On this page