Game Move History API
This document outlines the reverse-engineered specification for the Game Move History API in Dice Chess.
Unlike standard PGNs, this API does not just return a flat list of chess moves. Instead, it returns a massive State Machine History, where every small action (a roll of the dice, proposing a double, or moving a piece) is recorded as a complete snapshot (state) of the game.
Endpoint
Section titled “Endpoint”GET /api/game-move-history?gameId=<UUID>Authorization: Bearer <token>Admin Sync Endpoint (Trainer Backend)
Section titled “Admin Sync Endpoint (Trainer Backend)”The trainer backend exposes an admin-only endpoint to batch-import game metadata before move history is fetched.
For the full admin-side synchronization story — including the metadata list, the missing-history batch job, and the timeout/concurrency behavior — see Move Synchronization Lifecycle.
POST /api/admin/sync/games?limit=50&skip=0&player_id=<PLAYER_ID>&start_date_ms=<EPOCH_MS>Query Parameters
Section titled “Query Parameters”| Param | Type | Required | Description |
|---|---|---|---|
limit | int | No | Batch size (1..100). |
skip | int | No | Pagination offset for Dice Chess history API. |
player_id | string | No | Overrides configured default sync player id. |
start_date_ms | int | No | Inclusive lower bound (Unix epoch in milliseconds) for history filtering. |
When start_date_ms is provided, the history request includes filters.START_DATE and uses
ascending date sort (isAsc=true) to backfill from older games forward. Without it, sort stays
descending (isAsc=false).
The “State Machine” Concept
Section titled “The “State Machine” Concept”The API returns a JSON object where each key represents a sequential Step number (starting from "0"), and the value is the complete game state at that exact moment.
Because a single “Turn” in Dice Chess consists of a dice roll plus up to three micro-moves, you will see many Steps for just one actual Turn changing hands.
Step 0: The Initial State
Section titled “Step 0: The Initial State”The "0" step is crucial for bootstrapping the game view:
- Time: The
leftTimeobject shows the starting time for both players in milliseconds. - Bank: The
bankproperty represents the total combined bank. To find out how much a single player has wagered, you must divide this number by 2 (e.g., ifbankis 600, each player bet 300).
Deducing Hidden Actions (Resign, Draw, Double)
Section titled “Deducing Hidden Actions (Resign, Draw, Double)”A major quirk of this external API is that it does not provide explicit flags for actions like “Player Resigned”, “Player Offered Draw”, or “Player Offered Double”. These actions must be deduced purely by analyzing the transitions between states.
1. Resigning
Section titled “1. Resigning”If the game ends, the times stop ticking, and the position is not checkmate, it means a player resigned or disconnected.
2. Offering a Draw
Section titled “2. Offering a Draw”A draw offer is inferred heuristically from no-op transition states and clock behavior while one side decides. This can happen before a roll or during the opponent’s unfinished micro-turn. For a documented real-world interrupt sequence, see Draw Offer During Opponent Micro-Turn.
3. The Doubling Mechanic (X2 Mode)
Section titled “3. The Doubling Mechanic (X2 Mode)”In X2 mode, offering and accepting a double is the most complex sequence to parse. Below is an exhaustive breakdown of how to identify a Double action from the raw JSON state, using an actual game log from Steps 12 to 17.
Step 12: Turn Completes
Section titled “Step 12: Turn Completes”// Black finishes their move."12": { "fen": "r1bqkbnr/pppppppp/2n5/1N6/7P/7R/PPPPPPP1/R1BQKBN1 b Qkq - 4 1", ... "gameMoveHistoryMove": { "from": "B8", "to": "C6", "promotion": "NONE" }}- Status: Black made a move.
gameMoveHistoryMoveis populated, so theB8toC6squares are highlighted green on the board.
Step 13: Transition
Section titled “Step 13: Transition”// Highlights are cleared. Turn switches to White."13": { "fen": "r1bqkbnr/pppppppp/2n5/1N6/7P/7R/PPPPPPP1/R1BQKBN1 w Qkq - 4 1", ... "gameMoveHistoryMove": null}- Status:
gameMoveHistoryMovebecomesnull, clearing board highlights. The FEN active color is noww(White’s turn).
Step 14: White Evaluates / Offers Double
Section titled “Step 14: White Evaluates / Offers Double”"14": { "fen": "r1bqkbnr/pppppppp/2n5/1N6/7P/7R/PPPPPPP1/R1BQKBN1 w Qkq - 4 1", "bank": 600, "leftTime": { "303082" (White): 296734, "782580" (Black): 304599 }, "gameMoveHistoryMove": null}- Status: White’s time has decreased (from 298286 in Step 13 to 296734 here), meaning White was thinking. However, White has not rolled the dice yet (the
dicesarray still contains Black’s old roll). During this step, White clicked the X2 Double button. - Effect: Black’s time will now start ticking as Black decides whether to accept or fold.
Step 15: Black Accepts
Section titled “Step 15: Black Accepts”"15": { "bank": 1200, "leftTime": { "303082" (White): 296734, "782580" (Black): 304899 }}- Status: The
bankinstantly jumps from 600 to 1200. This is the definitive proof that Black accepted the Double.
Step 16: White Rolls Dice
Section titled “Step 16: White Rolls Dice”"16": { "bank": 1200, "dices": [ { "value": "B", "allowed": false, "used": false }, ... ]}- Status: White rolls the dice resulting in fresh dice values.
Step 17: White’s First Move
Section titled “Step 17: White’s First Move”"17": { "gameMoveHistoryMove": { "from": "E2", "to": "E4", "promotion": "NONE" }}- Status: White begins using the dice to make physical moves on the board.
The “Step” Object Schema
Section titled “The “Step” Object Schema”Every numbered step in the JSON object respects the following schema.
| Field | Type | Description |
|---|---|---|
fen | String | The standard FEN string representing the exact board configuration (including the active color). |
bank | Number | The total combined bank for the match at this specific moment. |
dices | Object[] | Array of exactly 3 dice objects representing the most recent roll. |
dices[].value | String | The piece rolled (e.g., "P", "K", "R", "n", "q"). Case denotes color. |
dices[].allowed | Boolean | true if this die can be legally played on the board. |
dices[].used | Boolean | true if the player has already executed the move associated with this die. |
leftTime | Record<string, number> | A dictionary mapping the player_id (String) to their remaining time in milliseconds. |
gameMoveHistoryMove | Object | null | Contains {from, to, promotion}. If not null, it represents the Delta physical piece move that just happened, which is used to render green square highlights. |