Sessions

Sessions are lobbies: a player opens one, friends join it, everyone readies up, and your game server takes it from there. The platform keeps the lobby; your servers host the match.

Switching it on

Switch the Sessions service on for your project in the console. Until you do, every /sessions route answers service-disabled. The environment's Sessions page lists its sessions, newest first, and can filter them by status.

The lifecycle

CONFIGURING ──(everyone present is ready)──> PREPARING_INSTANCE
                                                  │  your server reports
                                                  ▼
                                   AWAITING_PLAYERS ──> PLAYING ──> COMPLETE
                                         (any of these can become ERROR)
Status Meaning Moved there by
CONFIGURING The lobby is open: players join, leave and ready up Creating the session
PREPARING_INSTANCE Everyone present is ready; your server should start the match The last ready
AWAITING_PLAYERS Your server is up and waiting for players to connect Your server
PLAYING The match is under way Your server
COMPLETE The match ended Your server
ERROR Something went wrong Your server

The lobby (player routes)

Every lobby route takes the player's access token.

Route Body What it does
POST /sessions { gameMode, map, playerName?, uniqueNetId? } Opens a lobby with the caller as host. Answers 201
GET /sessions/:id Reads a lobby (a server key may too)
POST /sessions/:id/join { playerName?, uniqueNetId? } Takes a seat
POST /sessions/:id/leave none Gives up the caller's seat. Answers 204
POST /sessions/:id/ready { isReady } Marks the caller ready or not ready
POST /sessions/:id/players/:playerId/kick none The host removes a seated player
POST /sessions/:id/players/:playerId/promote none The host hands the host role to another seated player

gameMode and map are your own words, 1 to 60 characters each; the platform stores them and gives them back. playerName is the name the seat shows (1 to 40 characters, filtered as a display name is); without it the seat uses the player's display name, or Player when they have none. uniqueNetId (up to 200 characters) is the player's id on your online subsystem; it is stored with the seat for your own use and is not returned in the session today.

A session is returned as:

{
  "id": "0199a7d0-4f7a-7b02-a1c3-9e6f2b8d5c10",
  "status": "CONFIGURING",
  "gameMode": "coop",
  "map": "harbour",
  "conclusion": null,
  "seats": 4,
  "players": [
    {
      "playerId": "0199a7c3-0b2d-7e11-8c55-5f0e3d9a4b21",
      "playerName": "Ada",
      "isHost": true,
      "isReady": false
    },
    {
      "playerId": "0199a7c4-6e90-7a3f-b4d2-1c7e8f0a9b33",
      "playerName": "Grace",
      "isHost": false,
      "isReady": false
    }
  ],
  "createdAt": "2026-09-29T12:05:00.000Z"
}

Seats are listed host first, then in the order players joined.

Rules

  • A lobby has the seats its project gives it: 4 until an admin changes it on the project's page in the console, up to what the org's plan allows (8 on Free, 64 on Studio). Every session answers its seats. Joining a full lobby is refused with conflict, details.limit saying how many seats it has. Lowering the number leaves a fuller lobby its players; it takes nobody more.
  • A player joins by the session's id. There is no lobby browser: share the id however your game does (a join code your client shows, a friend invite, your own matchmaking).
  • Joining, readying, kicking and promoting work only while the session is CONFIGURING. Afterwards they answer conflict.
  • Only the host may kick or promote. A seated player who is not the host is refused with forbidden.
  • When a player readies and everybody else seated is already ready, the session moves to PREPARING_INSTANCE. There is no minimum head count: a host alone in a lobby who readies starts it. If your game needs more players, have your client wait before it offers Ready.
  • Leaving does not pass the host role on. A host who leaves while others are seated should promote somebody first.
  • Only players of the same environment can be seated.

Clients hear about every change the moment it happens over the sessions socket: seats taken and given up, readies, kicks, promotions, the status moving, who is connected, and your game's own messages between seats. See Realtime. There is no need to poll; read the session with GET /sessions/:id when your client has no socket open.

Your server's part

Once a session reaches PREPARING_INSTANCE, the platform's work is done and yours begins: start or assign a match server, get the players connected, and report progress with your server key.

curl -X POST https://api.greenmindmedia.com/api/platform/v1/sessions/$SESSION_ID/status \
  -H "Authorization: Bearer $GM_SERVER_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "PLAYING" }'
Field Rules
status AWAITING_PLAYERS, PLAYING, COMPLETE or ERROR
conclusion Optional, 1 to 60 characters, your own word for how it ended (victory, abandoned). Kept when the status is COMPLETE
error Optional, up to 500 characters. Kept when the status is ERROR

A session only moves forward:

From To
PREPARING_INSTANCE AWAITING_PLAYERS, PLAYING, ERROR
AWAITING_PLAYERS PLAYING, ERROR
PLAYING COMPLETE, ERROR

Any other move is refused with conflict, including any move out of CONFIGURING, which only the players' ready check makes. If two reports arrive at once, one succeeds and the other is refused with conflict: read the session and decide again.

How your server learns that a session is ready is up to you. Typically the host's client, on seeing PREPARING_INSTANCE (a session.status frame on the socket), asks your backend for a match server and passes the session id; your server then reads the session with GET /sessions/:id to see who is seated. Each report your server makes reaches every seat's socket as session.status.

Hosting

Today your servers host every match. The API a server calls does not assume where it runs, and hosting match servers for studios may come later.