Lobbies
Small, ad-hoc leaderboards, auto-matched by Kraty or pushed in from your own matchmaker, with progressive bot fill so they never look empty.
A lobby is a leaderboard for a subset of players. Reach for lobbies when the global leaderboard is too noisy, or when you want short-form, high-frequency competition.
Two ways to get one:
- Auto-matched: set up matchmaking parameters on the event, and Kraty handles the queue.
- External push: your own matchmaker (Steam, GameLift, Photon) picks the roster and tells Kraty.
Auto-matched lobbies
Kraty handles the queue. On the event, set:
| Field | What it does |
|---|---|
capacity | How many players make a "full" lobby. |
fillTimeoutSeconds | How long to wait before starting underfilled. |
fillBots | Pad empty slots with bots when the timeout hits, or leave them open. |
fillBy is the deadline computed from fillTimeoutSeconds: the
absolute timestamp the SDK surfaces on the lobby once it starts
forming.
When a player calls events.start, the SDK gets back either an
attempt (the lobby was active) or a 202 with a lobbyId (the
lobby is still forming, so poll lobbies.read(lobbyId) (or use
pollLobbyUntilActive) until it is active, then call
events.start again).
External lobbies
If your own matchmaker is the source of truth, POST the lobby up after match-make. Kraty creates the leaderboard, fills bots per the event config, and runs the rest:
POST /server/v1/games/{gameId}/events/{eventKey}/lobbies
Authorization: Bearer <server_integration api key>
Content-Type: application/json
{
"key": "match-abc123",
"externalPlayerIds": ["player_alice", "player_bob"],
"fillBots": true
}The key field is your studio's own idempotency token: POSTing
twice with the same key returns the existing lobby.
See the Recipes → Push a lobby from your own matchmaker for the SDK wrapper of this endpoint.
Lifecycle
Lobbies move through forming → active → closed. The transitions
fire webhooks (lobby.created,
lobby.started,
lobby.closed) so your game backend
can spin up servers, set up chat channels, or record results when
the time comes.
Progressive bot fill
When fillBots: true and the lobby is not filling with real
players, Kraty drips bots in over time instead of waiting the full
fillTimeoutSeconds and dropping them in all at once. Your "lobby
waiting" UI gets a natural "filling up" animation rather than a
30-second wait followed by a flood.
You read it from the SDK like this:
final lobby = await kraty.lobbies.read(lobbyId);
print('${lobby.participantCount} humans + ${lobby.botSlots} bots'
' / ${lobby.capacity}');
print('filled (clamped): ${lobby.filledSlots}');participantCount: real humans in the lobby.botSlots: bots ready to join. This grows over time as more bots become available; poll or open an SSE stream to redraw the slot UI as it changes.filledSlots:participantCount + botSlots, clamped tocapacityso a brief clock skew cannot show "5/4".
Default drip cadence is one bot every 5 seconds. For a 4-cap lobby:
| Time since the lobby formed | botSlots you will see |
|---|---|
| 0–5s | 0 |
| 5–10s | 1 |
| 10–15s | 2 |
| 15–20s | 3 |
past fillBy | the rest, all at once |
The lobby starts (status: 'active') as soon as humans + bots
reach capacity, either organically from the drip + new humans
joining, or via the fillBy backstop.
In the Flutter sample app's Lobby view, filled slots render as green person icons (humans) followed by purple android icons (bots), with empty slots greyed out; the purple bots appear over time as the drip progresses.