# API Changes (Not Yet Reflected in `backend/openapi/openapi.json`) This document lists additive API changes currently implemented in the Go backend. ## Summary Existing endpoints remain compatible. Added capabilities: 1. Position board persistence for live/admin ordering. 2. Stage session control (`start`/`end`) for event flow. 3. Stage history retrieval. 4. New state fields (`positionBoards`, `current_stage`, `last_stage`). ## 1) Position Board Endpoint - Method: `PUT` - Path: `/api/admin/positions/:board` - Auth: admin bearer token (`Authorization: Bearer `) ### Supported `:board` values - `preliminary` - `final` - `prelim_tiebreak` - `final_tiebreak` ### Request body ```json { "slots": [ { "playerId": 12, "groupKey": "A", "position": 1 }, { "playerId": 15, "groupKey": "A", "position": 2 }, { "playerId": 20, "groupKey": "B", "position": 1 } ] } ``` Fields: - `playerId` (integer, required) - `groupKey` (string, required) - `position` (integer > 0, required) Notes: - The request replaces all saved slots for the target board. - For `preliminary`, `players.group_code` is synchronized from `groupKey`. - Special value `UNASSIGNED` maps to empty player group. ### Response - `200 OK` with full updated admin state payload. ## 2) Stage Session Control Endpoints ### Start stage - Method: `POST` - Path: `/api/admin/stage/start` - Auth: admin bearer token Request body: ```json { "phase": "preliminary", "group": "A", "round": 2 } ``` Rules: - `phase` must be one of: - `preliminary` - `prelim_tiebreak` - `final` - `final_tiebreak` - `group` validation depends on phase: - `preliminary`: group code string (or `UNASSIGNED`) - `final`: `"1"` or `"2"` - tie-break phases: positive numeric string - `round` normalization: - `preliminary`: `1..3` - `final`: `1..2` - tie-break phases: always `1` - If another stage is active (started, not ended), API returns `409`. Response: - `200 OK` with full updated admin state payload. ### End stage - Method: `POST` - Path: `/api/admin/stage/end` - Auth: admin bearer token Rules: - Ends the currently active stage by setting `ended_at`. - If no active stage exists, API returns `400`. Response: - `200 OK` with full updated admin state payload. ## 3) Stage History Endpoint - Method: `GET` - Path: `/api/admin/stage/history` - Auth: admin bearer token Response: ```json { "items": [ { "id": 1, "phase": "preliminary", "group": "A", "round": 2, "startedAt": "2026-04-30T08:27:13Z", "endedAt": "2026-04-30T08:28:01Z" } ] } ``` ## 4) New State Fields Both endpoints now include these fields: - `GET /api/state` - `GET /api/admin/state` ```json { "positionBoards": { "preliminary": { "12": { "groupKey": "A", "position": 1 } }, "final": { "12": { "groupKey": "1", "position": 3 } }, "prelim_tiebreak": {}, "final_tiebreak": {} }, "current_stage": { "id": 7, "phase": "preliminary", "group": "A", "round": 2, "startedAt": "2026-04-30T09:00:00Z" }, "last_stage": { "id": 6, "phase": "final", "group": "1", "round": 1, "startedAt": "2026-04-30T08:45:00Z", "endedAt": "2026-04-30T08:55:00Z" } } ``` Notes: - `positionBoards` keys are player IDs as strings. - `current_stage` is `null` when no stage is active. - `last_stage` is `null` when no stage session has ever started. - `last_stage` is the most recently started session (ended or still active). ## Compatibility Impact - Additive only; existing consumers remain functional. - Consumers can ignore unknown fields safely. - Consumers needing control/monitoring can use new stage endpoints and fields.