REST API Specification

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