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
This commit is contained in:
cottongin
2026-03-15 19:21:35 -04:00
parent 3ed3af06ba
commit 0d0d20161b
6 changed files with 57 additions and 7 deletions

View File

@@ -36,6 +36,8 @@ A full-stack web application that helps groups pick games to play from various J
- **Live Voting API**: Real-time vote processing from external bots
- Accept live votes via REST API
- Real-time `vote.received` WebSocket event for stream overlays
- Per-session vote breakdown and paginated global vote history
- Automatic deduplication (1-second window)
- Timestamp-based game matching
- JWT authentication for security
@@ -249,6 +251,7 @@ The manifest is automatically generated during the build process, so you don't n
- `POST /api/sessions` - Create new session (admin)
- `POST /api/sessions/:id/close` - Close session (admin)
- `GET /api/sessions/:id/games` - Get games in session
- `GET /api/sessions/:id/votes` - Get per-game vote breakdown for a session
- `POST /api/sessions/:id/games` - Add game to session (admin)
- `POST /api/sessions/:id/chat-import` - Import chat log (admin)
@@ -258,7 +261,8 @@ The manifest is automatically generated during the build process, so you don't n
### Statistics
- `GET /api/stats` - Get overall statistics
### Live Votes
### Votes
- `GET /api/votes` - Paginated vote history with filtering
- `POST /api/votes/live` - Submit real-time vote (admin)
### Webhooks

View File

@@ -40,6 +40,8 @@ All REST endpoints are prefixed with `/api/` except `/health`.
- `GET /api/sessions/active`
- `GET /api/sessions/{id}`
- `GET /api/sessions/{id}/games`
- `GET /api/sessions/{id}/votes`
- `GET /api/votes`
- `GET /api/stats`
- `POST /api/pick`
- `GET /health`
@@ -82,7 +84,7 @@ SQLite stores booleans as integers (0/1). In request bodies, pass JavaScript boo
## Pagination
No pagination. All list endpoints return full result sets.
Most list endpoints return full result sets. The exception is `GET /api/votes`, which supports pagination via `page` and `limit` query parameters (default: page 1, limit 50, max 100).
## Quick Reference
@@ -128,6 +130,7 @@ No pagination. All list endpoints return full result sets.
| DELETE | `/api/sessions/{id}` | Yes | Delete a session |
| POST | `/api/sessions/{id}/close` | Yes | Close a session |
| GET | `/api/sessions/{id}/games` | No | List games in a session |
| GET | `/api/sessions/{id}/votes` | No | Get per-game vote breakdown for a session |
| POST | `/api/sessions/{id}/games` | Yes | Add a game to a session |
| POST | `/api/sessions/{id}/chat-import` | Yes | Import chat log for vote processing |
| GET | `/api/sessions/{id}/export` | Yes | Export session |
@@ -154,6 +157,7 @@ No pagination. All list endpoints return full result sets.
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET | `/api/votes` | No | Paginated vote history with filtering |
| POST | `/api/votes/live` | Yes | Record a live vote (up/down) |
### Webhooks

View File

@@ -270,7 +270,7 @@ curl -X DELETE "http://localhost:5000/api/sessions/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.
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).

View File

@@ -132,6 +132,7 @@ The WebSocket server runs at `/api/sessions/live` on the same host and port as t
| `game.added` | Session subscribers | `POST /api/sessions/{id}/games` |
| `session.ended` | Session subscribers | `POST /api/sessions/{id}/close` |
| `player-count.updated` | Session subscribers | `PATCH /api/sessions/{sessionId}/games/{sessionGameId}/player-count` |
| `vote.received` | Session subscribers | `POST /api/votes/live` (live votes only, not chat-import) |
`session.started` goes to every authenticated client. The others go only to clients that have subscribed to the relevant session via `{ "type": "subscribe", "sessionId": 3 }`.
@@ -157,7 +158,7 @@ All events use this envelope:
|---------|----------|-----------|
| **Connection** | Stateless HTTP | Persistent |
| **Auth** | Secret in config | JWT per connection |
| **Events** | `game.added` | `session.started`, `game.added`, `session.ended`, `player-count.updated` |
| **Events** | `game.added` | `session.started`, `game.added`, `session.ended`, `player-count.updated`, `vote.received` |
| **Latency** | Higher (HTTP round trip) | Lower (push) |
| **Reliability** | Logged, auditable | Best-effort |

View File

@@ -85,13 +85,53 @@ ws://localhost:5000/api/sessions/live
}
}
// Vote received (live votes only, not chat-import)
{
"type": "vote.received",
"timestamp": "2025-11-01T...",
"data": {
"sessionId": 123,
"game": { "id": 42, "title": "Quiplash 3", "pack_name": "Party Pack 7" },
"vote": { "username": "viewer123", "type": "up", "timestamp": "2025-11-01T20:30:00Z" },
"totals": { "upvotes": 14, "downvotes": 3, "popularity_score": 11 }
}
}
// Pong
{ "type": "pong" }
```
---
## Live Voting
## Votes
### Get Vote History
```http
GET /api/votes?session_id=5&game_id=42&username=viewer123&vote_type=up&page=1&limit=50
```
**Response (200)**:
```json
{
"votes": [
{
"id": 891,
"session_id": 5,
"game_id": 42,
"game_title": "Quiplash 3",
"pack_name": "Party Pack 7",
"username": "viewer123",
"vote_type": "up",
"timestamp": "2025-11-01T20:30:00.000Z",
"created_at": "2025-11-01T20:30:01.000Z"
}
],
"pagination": { "page": 1, "limit": 50, "total": 237, "total_pages": 5 }
}
```
All query parameters are optional. No authentication required.
### Submit Live Vote

View File

@@ -696,8 +696,9 @@ curl -X GET "http://localhost:5000/api/webhooks/1/logs" \
- `game.started` - Triggered when the Jackbox room becomes locked (gameplay has begun). Detected by polling the Jackbox REST API every 10 seconds via the room monitor. Sent to clients subscribed to that session. Includes `roomCode` and `maxPlayers`.
- `audience.joined` - Triggered when the app successfully joins a Jackbox room as an audience member for player count tracking. Sent to clients subscribed to that session.
- `player-count.updated` - Triggered when the player count for a game is updated. Sent to clients subscribed to that session.
- `vote.received` - Triggered when a live vote is recorded via `POST /api/votes/live`. Sent to clients subscribed to that session. Includes voter username, vote direction, game info, and updated global vote totals. Does **not** fire for chat-import votes.
> **Tip:** To receive `session.started` events, your bot only needs to authenticate — no subscription is needed. Once you receive a `session.started` event, subscribe to the new session ID to receive `game.added` and `session.ended` events for it.
> **Tip:** To receive `session.started` events, your bot only needs to authenticate — no subscription is needed. Once you receive a `session.started` event, subscribe to the new session ID to receive `game.added`, `vote.received`, and `session.ended` events for it.
### Event Lifecycle (for a game with room code)
@@ -711,7 +712,7 @@ When a game is added with a room code, events fire in this order:
Room monitoring and player counting are separate systems. The room monitor (`room-monitor.js`) handles steps 1-2 and then hands off to the player count checker (`player-count-checker.js`) for steps 3-5.
More events may be added in the future (e.g., `vote.recorded`).
More events may be added in the future.
---