Docs/Hosted Matchmaking/The Ticket Lifecycle
Hosted Matchmaking

The ticket lifecycle

For the "players join over time" case — building a lobby that fills up rather than starting from a known list. Four explicit steps, in order.

1. Create an empty ticket

POST /matchmaking/hosted/ticket?game=X — starts a forming ticket with nobody in it yet. Returns a ticketId.

2. Add players as they connect

POST /matchmaking/hosted/ticket/:id/players?game=X, body { playerId } — one call per player, whenever they show up. Fails with 409 if that player isn't currently connected, or the ticket's already full.

3. Promote when you say it's ready

POST /matchmaking/hosted/ticket/:id/promote?game=X — there is no automatic promotion. No size threshold, no timer. The ticket only becomes visible in the pool once your backend explicitly promotes it.

4. Start the match

POST /matchmaking/hosted/start-match?game=X, body { groupIds: [...] } — fires the match immediately from one or more promoted groups. No countdown; your call to this endpoint is the decision.

text
POST /ticket              →  { ticketId }
POST /ticket/:id/players  →  { result: "ok" }     (repeat per player)
POST /ticket/:id/promote  →  { group }             (now visible via GET /pool)
POST /start-match         →  match begins
If your tenant server ticks on a fixed interval to check for full lobbies, guard against overlapping ticks — a slow request from one tick colliding with the next has caused real duplicate-submission bugs elsewhere in this codebase. A simple in-flight flag per ticket is enough.