> ## Documentation Index
> Fetch the complete documentation index at: https://docs.playflowcloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Lobbies Quickstart

> Go from zero to a working multiplayer lobby in 5 minutes using nothing but curl.

This guide gets you a working lobby in under 5 minutes. No dashboard setup. No player auth. Just curl.

By the end, you'll have created a lobby, joined it with a second player, updated player state, and torn it all down.

## Prerequisites

* A PlayFlow project (free tier works — [sign up here](https://app.playflowcloud.com))
* Your **Client API Key** (from Project Settings → starts with `pfclient_`)

<Warning>
  Use the **client** key (`pfclient_*`) for anything a game client can do. Use the **server** key (`pf_*`) only for trusted backend services or admin operations.
</Warning>

***

## 1. Create a Lobby

A lobby is created by a "host" player. The host is whoever sends the `x-player-id` header on the create request.

```bash theme={null}
curl -X POST "https://api.computeflow.cloud/api/v3/lobbies/default" \
  -H "api-key: pfclient_YOUR_KEY" \
  -H "x-player-id: player1" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My First Lobby",
    "maxPlayers": 4
  }'
```

**Response:**

```json theme={null}
{
  "id": "a1b2c3d4-...",
  "code": "MEOW-42",
  "config": "default",
  "status": "waiting",
  "host": "player1",
  "currentPlayers": 1,
  "maxPlayers": 4,
  "players": [
    { "id": "player1", "state": null, "isHost": true }
  ],
  ...
}
```

<Check>
  **You just made a lobby.** No dashboard config was needed — PlayFlow used defaults. Note the `code` field: that's the invite code your players share.
</Check>

### About `{config}`

The `default` in the URL is a **lobby config name**. If no config with that name exists in your dashboard, PlayFlow uses sensible defaults:

* `maxPlayers: 2`
* `timeout: 300s`
* `serverSize: small`
* Build: latest `default`

For production games, you'll create named configs in the dashboard (`casual`, `ranked_2v2`, etc.) with custom matchmaking rules and server overrides. But you don't need to yet.

***

## 2. Join as a Second Player

Share the invite code `MEOW-42` with your friend. They call:

```bash theme={null}
curl -X POST "https://api.computeflow.cloud/api/v3/lobbies/default/join" \
  -H "api-key: pfclient_YOUR_KEY" \
  -H "x-player-id: player2" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "MEOW-42",
    "state": { "team": "blue", "ready": false }
  }'
```

They could also join by **lobby ID** if they have it:

```bash theme={null}
curl -X POST "https://api.computeflow.cloud/api/v3/lobbies/default/join" \
  -H "api-key: pfclient_YOUR_KEY" \
  -H "x-player-id: player2" \
  -H "Content-Type: application/json" \
  -d '{
    "lobbyId": "a1b2c3d4-..."
  }'
```

The response is the full lobby, now with 2 players:

```json theme={null}
{
  "id": "a1b2c3d4-...",
  "currentPlayers": 2,
  "players": [
    { "id": "player1", "state": null, "isHost": true },
    { "id": "player2", "state": { "team": "blue", "ready": false }, "isHost": false }
  ],
  ...
}
```

***

## 3. Check Your Current Lobby

Any player can check which lobby they're in using `/me`:

```bash theme={null}
curl "https://api.computeflow.cloud/api/v3/lobbies/default/me" \
  -H "api-key: pfclient_YOUR_KEY" \
  -H "x-player-id: player2"
```

Returns the full lobby state. If you're not in a lobby, returns `404`.

<Tip>
  `/me` is the player-centric primitive throughout the API. Instead of tracking lobby IDs in your game, just use `/me` endpoints — PlayFlow finds your lobby automatically from the `x-player-id` header.
</Tip>

***

## 4. Update Player State

Ready up, pick a character, set your MMR — anything goes in player state. The server merges your updates into existing state.

```bash theme={null}
curl -X PATCH "https://api.computeflow.cloud/api/v3/lobbies/default/me" \
  -H "api-key: pfclient_YOUR_KEY" \
  -H "x-player-id: player2" \
  -H "Content-Type: application/json" \
  -d '{
    "state": {
      "ready": true,
      "loadout": "sniper",
      "mmr": 1500
    }
  }'
```

The response shows `player2`'s updated state:

```json theme={null}
{
  "players": [
    { "id": "player1", "state": null, "isHost": true },
    {
      "id": "player2",
      "state": {
        "team": "blue",
        "ready": true,
        "loadout": "sniper",
        "mmr": 1500
      },
      "isHost": false
    }
  ],
  ...
}
```

<Info>
  State updates **merge** — existing keys are preserved unless overwritten. Setting `ready: true` doesn't wipe out `team: blue`.
</Info>

***

## 5. Start the Game

When ready, the host launches a game server directly:

```bash theme={null}
curl -X POST "https://api.computeflow.cloud/api/v3/lobbies/default/me/start" \
  -H "api-key: pfclient_YOUR_KEY" \
  -H "x-player-id: player1"
```

The response now has `server` populated:

```json theme={null}
{
  "status": "in_game",
  "server": {
    "instance_id": "srv-abc123",
    "status": "launching",
    "region": "us-east",
    "network_ports": [
      {
        "name": "game_udp",
        "host": "203.0.113.42",
        "external_port": 30234,
        "internal_port": 7770,
        "protocol": "udp",
        "tls_enabled": false
      }
    ]
  },
  ...
}
```

Use `server.network_ports[0].host` and `server.network_ports[0].external_port` to connect your game client. The `server` block is the same shape as `GET /v3/servers/{instance_id}`. The server transitions from `launching` → `running` in \~10-30 seconds (or \~5s with pool servers).

<Warning>
  Only the **host** can start the game. If a non-host tries, they get a `403 Not host`.
</Warning>

***

## 6. Leave (Cleanup)

Every player leaves with:

```bash theme={null}
curl -X DELETE "https://api.computeflow.cloud/api/v3/lobbies/default/me" \
  -H "api-key: pfclient_YOUR_KEY" \
  -H "x-player-id: player2"
```

When the **last player** leaves, the lobby auto-deletes. The response is `{"status": "lobby_deleted"}`.

If the **host** leaves while others remain, host transfers to the next player automatically.

***

## That's It

You've now exercised the full lobby lifecycle using just 6 API calls. The full API adds matchmaking, host-only actions (kick, settings), invite code joining, lobby browsing, real-time SSE updates, and more — but this is the 80% of what most games need.

<CardGroup cols={2}>
  <Card title="Lobby Lifecycle" icon="arrows-rotate" href="/lobbies/lifecycle">
    Host-only actions (kick, settings, transfer host), leaving behavior, error handling.
  </Card>

  <Card title="Matchmaking" icon="swords" href="/lobbies/matchmaking">
    Skip the manual "start" — let PlayFlow find opponents automatically.
  </Card>

  <Card title="Real-time Events" icon="bolt" href="/lobbies/real-time">
    Stop polling. Subscribe to live events with SSE.
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/lobbies-and-matchmaking/createlobby">
    Every endpoint with full schemas and try-it-out.
  </Card>
</CardGroup>
