Files
jackboxpartypack-gamepicker/docs/api/guides/session-lifecycle.md
cottongin 0d0d20161b docs: update remaining docs with vote tracking API changes
Update README.md, docs/api/README.md, session-lifecycle guide,
webhooks-and-events guide, and archive docs (BOT_INTEGRATION,
API_QUICK_REFERENCE) with new endpoints and vote.received event.

Made-with: Cursor
2026-03-15 19:21:35 -04:00

288 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 (AZ) and digits (09) 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`, `player-count.updated`, and `vote.received`. 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`.