REST API Specification
Base path: /api
All request and response bodies are application/json.
Error Format
{
"error": "GAME_NOT_FOUND",
"message": "No game with code 'Blue-Dancing-Horse' exists."
}
| Code | HTTP | Meaning |
|---|---|---|
| GAME_NOT_FOUND | 404 | Game code does not exist |
| GAME_FULL | 409 | Max players (40) reached |
| PLAYER_NOT_FOUND | 404 | Player not in this game |
| QUESTION_TIMEOUT | 410 | Answer after time limit |
| VALIDATION_ERROR | 400 | Missing or invalid fields |
Player Input
POST /api/games/{code}/players — join
Register a player. Allowed in AUTO_LOBBY, COUNTDOWN, PLAYING, REVIEWING.
Request:
{
"name": "Bob"
}
Response 201 Created:
{
"playerId": "p-2",
"name": "Bob",
"gameCode": "Blue-Dancing-Horse",
"state": "AUTO_LOBBY"
}
POST /api/games/{code}/questions/{index}/answers — answer
Submit min/max answer for current question. Only in PLAYING state.
Request:
{
"playerId": "p-2",
"userMin": 380,
"userMax": 450
}
Response 201 Created:
{
"questionIndex": 3,
"playerId": "p-2",
"delta": 70,
"submittedAt": 1700000042000
}
GET /api/games/{code}/questions/current — getQuestion
Get the current question. Only in PLAYING state.
Response 200 OK:
{
"questionIndex": 3,
"questionText": "How tall is the Empire State Building?",
"isoUnit": "m",
"defaultMin": 0,
"defaultMax": 1000,
"illustrationUrl": "https://media.example.com/media-hash",
"timeRemainingMs": 42000
}
POST /api/games/{code}/next — signalNext
Signal readiness to advance to the next question or phase. Used in REVIEWING state.
Request:
{
"playerId": "p-2"
}
Response 200 OK:
{
"status": "OK"
}
GET /api/games/{code}/results — getResults
Final results. Available in RESULTS, FINISHED, COOLDOWN.
Response 200 OK:
{
"code": "Blue-Dancing-Horse",
"state": "RESULTS",
"rankings": [
{ "rank": 1, "playerId": "p-3", "name": "Carol" },
{ "rank": 2, "playerId": "p-2", "name": "Bob" }
],
"fastestAvgResponseMs": { "playerId": "p-3", "name": "Carol", "avgMs": 8200 },
"slowestAvgResponseMs": { "playerId": "p-2", "name": "Bob", "avgMs": 14500 },
"achievements": [
{ "title": "The Sniper", "name": "Carol", "detail": "Smallest total range for correct answers." },
{ "title": "The Rock", "name": "Bob", "detail": "Most consistent estimation ranges." }
]
}
Common Screen — Game State
GET /api/games/{code}/state — getGameState
Current game state for the common screen display.
Response 200 OK:
{
"code": "Blue-Dancing-Horse",
"state": "PLAYING",
"currentQuestionIndex": 3,
"numberOfQuestions": 10,
"playersJoined": 12,
"answersReceived": 8,
"timeRemainingMs": 42000,
"question": {
"questionText": "How tall is the Empire State Building?",
"isoUnit": "m",
"illustrationUrl": "https://media.example.com/media-hash"
}
}
During AUTO_LOBBY, includes lobby timer:
{
"state": "AUTO_LOBBY",
"lobbyTimeRemainingMs": 245000,
"playersJoined": 5
}
During REVIEWING:
{
"state": "REVIEWING",
"playersReady": 7,
"review": {
"correctValue": 443,
"stats": {
"percentCorrect": 66.7,
"mean": 450.5,
"median": 445.0,
"spread": 120.0
},
"facts": [
{ "text": "The group has excellent knowledge about this!" },
{ "text": "We had some wild outliers this round!" }
]
}
}
During FINISHED:
{
"state": "FINISHED",
"timeRemainingMs": 25000,
"results": { ... }
}