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

10 KiB
Raw Blame History

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 for details.

Endpoint: POST /api/sessions

# 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):

{
  "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 to select a game with filters and repeat avoidance. Then add that game to the session.

# 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):

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

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

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.

# 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

# 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.

When the player count changes (via room monitor or manual update), a player-count.updated WebSocket event is broadcast to session subscribers.

# 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

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):

{
  "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

  • 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.
# 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}

curl -X DELETE "http://localhost:5000/api/sessions/5" \
  -H "Authorization: Bearer $TOKEN"

Response (200 OK):

{
  "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.


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.