docs: comprehensive API documentation from source code
Replace existing docs with fresh documentation built entirely from source code analysis. OpenAPI 3.1 spec as source of truth, plus human-readable Markdown with curl examples, response samples, and workflow guides. - OpenAPI 3.1 spec covering all 42 endpoints (validated against source) - 7 endpoint reference docs (auth, games, sessions, picker, stats, votes, webhooks) - WebSocket protocol documentation (auth, subscriptions, 4 event types) - 4 guide documents (getting started, session lifecycle, voting, webhooks) - API README with overview, auth docs, and quick reference table - Old docs archived to docs/archive/ Made-with: Cursor
This commit is contained in:
287
docs/api/guides/session-lifecycle.md
Normal file
287
docs/api/guides/session-lifecycle.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# Session Lifecycle Guide
|
||||
|
||||
This guide walks through the full lifecycle of a Jackbox gaming session—from creation through closing and deletion—with narrative explanations, behavior notes, and curl examples.
|
||||
|
||||
**Base URL:** `http://localhost:5000`
|
||||
**Authentication:** All write operations require a Bearer token. Set `TOKEN` in your shell and use `-H "Authorization: Bearer $TOKEN"` in curl examples.
|
||||
|
||||
---
|
||||
|
||||
## 1. Creating a Session
|
||||
|
||||
Only **one active session** can exist at a time. If an active session already exists, you must close it before creating a new one.
|
||||
|
||||
Notes are optional; they help you remember what a session was for (e.g., "Friday game night", "Birthday party").
|
||||
|
||||
Creating a session triggers a **`session.started`** WebSocket event broadcast to all authenticated clients. See [Real-time updates via WebSocket](#9-real-time-updates-via-websocket) for details.
|
||||
|
||||
**Endpoint:** [POST /api/sessions](../endpoints/sessions.md#post-apisessions)
|
||||
|
||||
```bash
|
||||
# Create a session with notes
|
||||
curl -X POST "http://localhost:5000/api/sessions" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"notes": "Friday game night"}'
|
||||
|
||||
# Create a session without notes (body can be empty)
|
||||
curl -X POST "http://localhost:5000/api/sessions" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{}'
|
||||
```
|
||||
|
||||
**Response (201 Created):**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 5,
|
||||
"notes": "Friday game night",
|
||||
"is_active": 1,
|
||||
"created_at": "2026-03-15T19:00:00.000Z",
|
||||
"closed_at": null
|
||||
}
|
||||
```
|
||||
|
||||
If an active session already exists, you receive `400` with a message like `"An active session already exists. Please close it before creating a new one."` and an `activeSessionId` in the response.
|
||||
|
||||
---
|
||||
|
||||
## 2. Adding Games
|
||||
|
||||
You can add games in two ways: via the **picker** (weighted random selection) or **manually** by specifying a game ID.
|
||||
|
||||
### Via the Picker
|
||||
|
||||
First, use [POST /api/pick](../endpoints/picker.md#post-apipick) to select a game with filters and repeat avoidance. Then add that game to the session.
|
||||
|
||||
```bash
|
||||
# 1. Pick a game (optionally filter by player count, session for repeat avoidance)
|
||||
GAME=$(curl -s -X POST "http://localhost:5000/api/pick" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"playerCount": 6, "sessionId": 5}' | jq -r '.game.id')
|
||||
|
||||
# 2. Add the picked game to the session
|
||||
curl -X POST "http://localhost:5000/api/sessions/5/games" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"game_id\": $GAME, \"manually_added\": false}"
|
||||
```
|
||||
|
||||
### Manual Addition
|
||||
|
||||
Add a game directly by its `game_id` (from the games catalog):
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:5000/api/sessions/5/games" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"game_id": 42, "manually_added": true, "room_code": "ABCD"}'
|
||||
```
|
||||
|
||||
**Endpoint:** [POST /api/sessions/{id}/games](../endpoints/sessions.md#post-apisessionsidgames)
|
||||
|
||||
### Side Effects of Adding a Game
|
||||
|
||||
When you add a game to an active session, several things happen automatically:
|
||||
|
||||
1. **Previous `playing` games** are auto-transitioned to **`played`**. At most one game is `playing` at a time.
|
||||
2. The game's **`play_count`** is incremented in the catalog.
|
||||
3. The **`game.added`** webhook is fired (if you have webhooks configured) and a **`game.added`** WebSocket event is broadcast to session subscribers.
|
||||
4. If you provide a **`room_code`**, the room monitor is **auto-started** for player count tracking.
|
||||
|
||||
Newly added games start with status **`playing`**.
|
||||
|
||||
---
|
||||
|
||||
## 3. Tracking Game Status
|
||||
|
||||
Each game in a session has a status: **`playing`**, **`played`**, or **`skipped`**.
|
||||
|
||||
| Status | Meaning |
|
||||
|----------|-------------------------------------------|
|
||||
| `playing`| Currently being played (at most one at a time) |
|
||||
| `played` | Finished playing |
|
||||
| `skipped`| Skipped (e.g., technical issues); stays skipped |
|
||||
|
||||
**Behavior:** When you change a game's status to **`playing`**, any other games with status `playing` are automatically set to **`played`**. Skipped games are never auto-transitioned; they remain `skipped`.
|
||||
|
||||
**Endpoint:** [PATCH /api/sessions/{sessionId}/games/{sessionGameId}/status](../endpoints/sessions.md#patch-apisessionssessionidgamessessiongameidstatus)
|
||||
|
||||
**Important:** In session game sub-routes, `sessionGameId` refers to **`session_games.id`** (the row in the `session_games` table), **not** `games.id`. When listing session games with `GET /api/sessions/{id}/games`, the `id` field in each object is the `session_games.id`.
|
||||
|
||||
```bash
|
||||
# Mark a game as played (sessionGameId 14, not game_id)
|
||||
curl -X PATCH "http://localhost:5000/api/sessions/5/games/14/status" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"status": "played"}'
|
||||
|
||||
# Mark a game as playing (others playing → played)
|
||||
curl -X PATCH "http://localhost:5000/api/sessions/5/games/14/status" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"status": "playing"}'
|
||||
|
||||
# Mark a game as skipped
|
||||
curl -X PATCH "http://localhost:5000/api/sessions/5/games/14/status" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"status": "skipped"}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Room Codes
|
||||
|
||||
Room codes are 4-character strings used by Jackbox games for lobby entry. Valid format: exactly 4 characters, uppercase letters (A–Z) and digits (0–9) only. Example: `ABCD`, `XY9Z`.
|
||||
|
||||
A room code enables **room monitoring** for player count. You can set or update it when adding a game or via a dedicated PATCH endpoint.
|
||||
|
||||
**Endpoint:** [PATCH /api/sessions/{sessionId}/games/{sessionGameId}/room-code](../endpoints/sessions.md#patch-apisessionssessionidgamessessiongameidroom-code)
|
||||
|
||||
```bash
|
||||
# Set room code when adding a game
|
||||
curl -X POST "http://localhost:5000/api/sessions/5/games" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"game_id": 42, "room_code": "ABCD"}'
|
||||
|
||||
# Update room code later
|
||||
curl -X PATCH "http://localhost:5000/api/sessions/5/games/14/room-code" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"room_code": "XY9Z"}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Player Count Monitoring
|
||||
|
||||
For games with a room code, you can track how many players join. The room monitor polls the Jackbox lobby to detect player count changes.
|
||||
|
||||
- **Start monitoring:** [POST /api/sessions/{sessionId}/games/{sessionGameId}/start-player-check](../endpoints/sessions.md#post-apisessionssessionidgamessessiongameidstart-player-check)
|
||||
- **Stop monitoring:** [POST /api/sessions/{sessionId}/games/{sessionGameId}/stop-player-check](../endpoints/sessions.md#post-apisessionssessionidgamessessiongameidstop-player-check)
|
||||
- **Manual update:** [PATCH /api/sessions/{sessionId}/games/{sessionGameId}/player-count](../endpoints/sessions.md#patch-apisessionssessionidgamessessiongameidplayer-count)
|
||||
|
||||
When the player count changes (via room monitor or manual update), a **`player-count.updated`** WebSocket event is broadcast to session subscribers.
|
||||
|
||||
```bash
|
||||
# Start room monitor (game must have a room code)
|
||||
curl -X POST "http://localhost:5000/api/sessions/5/games/14/start-player-check" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Manually set player count
|
||||
curl -X PATCH "http://localhost:5000/api/sessions/5/games/14/player-count" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"player_count": 6}'
|
||||
|
||||
# Stop monitoring
|
||||
curl -X POST "http://localhost:5000/api/sessions/5/games/14/stop-player-check" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Closing Sessions
|
||||
|
||||
Closing a session marks it as inactive. The API:
|
||||
|
||||
1. Auto-finalizes all games with status **`playing`** to **`played`**
|
||||
2. Sets `closed_at` and `is_active = 0`
|
||||
3. Triggers a **`session.ended`** WebSocket broadcast to session subscribers
|
||||
|
||||
You can add or update session notes in the close request body.
|
||||
|
||||
**Endpoint:** [POST /api/sessions/{id}/close](../endpoints/sessions.md#post-apisessionsidclose)
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:5000/api/sessions/5/close" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"notes": "Great session!"}'
|
||||
```
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 5,
|
||||
"notes": "Great session!",
|
||||
"is_active": 0,
|
||||
"created_at": "2026-03-15T19:00:00.000Z",
|
||||
"closed_at": "2026-03-15T23:30:00.000Z",
|
||||
"games_played": 4
|
||||
}
|
||||
```
|
||||
|
||||
You cannot add games to a closed session.
|
||||
|
||||
---
|
||||
|
||||
## 7. Exporting Session Data
|
||||
|
||||
Export a session in two formats: **JSON** (structured) or **TXT** (human-readable).
|
||||
|
||||
**Endpoint:** [GET /api/sessions/{id}/export](../endpoints/sessions.md#get-apisessionsidexport)
|
||||
|
||||
- **JSON** (`?format=json`): Includes `session`, `games`, and `chat_logs` as structured data. Useful for archival or integrations.
|
||||
- **TXT** (default): Human-readable plaintext with headers and sections.
|
||||
|
||||
```bash
|
||||
# Export as JSON
|
||||
curl -o session-5.json "http://localhost:5000/api/sessions/5/export?format=json" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Export as TXT (default)
|
||||
curl -o session-5.txt "http://localhost:5000/api/sessions/5/export" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Deleting Sessions
|
||||
|
||||
Sessions must be **closed** before deletion. Active sessions cannot be deleted.
|
||||
|
||||
Deletion **cascades** to related data:
|
||||
|
||||
- `session_games` rows are deleted
|
||||
- `chat_logs` rows are deleted
|
||||
|
||||
**Endpoint:** [DELETE /api/sessions/{id}](../endpoints/sessions.md#delete-apisessionsid)
|
||||
|
||||
```bash
|
||||
curl -X DELETE "http://localhost:5000/api/sessions/5" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Session deleted successfully",
|
||||
"sessionId": 5
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Real-time Updates via WebSocket
|
||||
|
||||
The API provides real-time updates over WebSocket for session events: `session.started`, `game.added`, `session.ended`, and `player-count.updated`. Connect to `/api/sessions/live`, authenticate with your JWT, and subscribe to session IDs to receive these events without polling.
|
||||
|
||||
For connection setup, message types, and event payloads, see [WebSocket Protocol](../websocket.md).
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference: sessionGameId vs game_id
|
||||
|
||||
| Context | ID meaning | Example |
|
||||
|---------|------------|---------|
|
||||
| `POST /api/sessions/{id}/games` body | `game_id` = catalog `games.id` | `{"game_id": 42}` |
|
||||
| `GET /api/sessions/{id}/games` response `id` | `session_games.id` | Use `14` in sub-routes |
|
||||
| `PATCH .../games/{sessionGameId}/status` | `sessionGameId` = `session_games.id` | `/sessions/5/games/14/status` |
|
||||
|
||||
When in doubt: session game sub-routes use **`session_games.id`**, not `games.id`.
|
||||
Reference in New Issue
Block a user