Real-time popularity voting. Bots or integrations send votes during live gaming sessions. Votes are matched to the currently-playing game using timestamp intervals.
Submit a real-time up/down vote for the game currently being played. Automatically finds the active session and matches the vote to the correct game using the provided timestamp and session game intervals.
### Authentication
Bearer token required. Include in header: `Authorization: Bearer <token>`.
### Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| username | string | Yes | Identifier for the voter (used for deduplication) |
| vote | string | Yes | `"up"` or `"down"` |
| timestamp | string | Yes | ISO 8601 timestamp when the vote occurred |
```json
{
"username": "viewer123",
"vote": "up",
"timestamp": "2026-03-15T20:30:00Z"
}
```
### Behavior
- Finds the active session (single session with `is_active = 1`).
- Matches the vote timestamp to the game being played at that time (uses interval between consecutive `played_at` timestamps).
- Updates game `upvotes`, `downvotes`, and `popularity_score` atomically in a transaction.
- **Deduplication:** Rejects votes from the same username within a 1-second window (409 Conflict).
- Broadcasts a `vote.received` WebSocket event to all clients subscribed to the active session. See [WebSocket Protocol](../websocket.md#votereceived) for event payload.
| 400 | `{ "error": "vote must be either \"up\" or \"down\"" }` | Invalid vote value |
| 400 | `{ "error": "Invalid timestamp format. Use ISO 8601 format (e.g., 2025-11-01T20:30:00Z)" }` | Invalid timestamp |
| 404 | `{ "error": "No active session found" }` | No session with `is_active = 1` |
| 404 | `{ "error": "No games have been played in the active session yet" }` | Active session has no games |
| 404 | `{ "error": "Vote timestamp does not match any game in the active session", "debug": { "voteTimestamp": "2026-03-15T20:30:00Z", "sessionGames": [{ "title": "Quiplash 3", "played_at": "..." }] } }` | Timestamp outside any game interval |
| 409 | `{ "error": "Duplicate vote detected (within 1 second of previous vote)", "message": "Please wait at least 1 second between votes", "timeSinceLastVote": 0.5 }` | Same username voted within 1 second |
| 500 | `{ "error": "..." }` | Server error |
### Example
```bash
curl -X POST "http://localhost:5000/api/votes/live" \