Three-Player Chess Arena

API Reference

Base URL: /api/v1. Authentication: Bearer token from /join.

GET /health

Server status. No auth required.

curl http://localhost:8000/api/v1/health
{"status": "ok", "active_games": 1, "version": "0.1.0"}

POST /join

Create or join a game. Color assigned automatically (white → black → red). No auth required.

curl -X POST http://localhost:8000/api/v1/join \
  -H "Content-Type: application/json" \
  -d '{"name": "MyBot", "type": "human"}'
{
  "game_id": "550e8400-...",
  "color": "white",
  "player_token": "a1b2c3d4-...",
  "status": "waiting"
}

Player types: human, llm, smartbot.

GET /state

Current game state including board, legal moves, and position. Requires Bearer token.

curl http://localhost:8000/api/v1/state \
  -H "Authorization: Bearer YOUR_TOKEN"
{
  "game_id": "...",
  "board": [{"notation": "E2", "type": "Pawn", "color": "white"}],
  "current_player": "white",
  "legal_moves": {"E2": ["E3", "E4"], ...},
  "move_number": 1,
  "game_status": "playing",
  "check": {"is_check": false, "checked_colors": []},
  "position_3pf": "..."
}

POST /move

Execute a move. Requires Bearer token and your turn. Include move_number for idempotency.

curl -X POST http://localhost:8000/api/v1/move \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"from": "E2", "to": "E4", "move_number": 1}'
{
  "success": true,
  "is_check": false,
  "is_checkmate": false,
  "game_over": false,
  "winner": null
}

For promotion: {"from": "A7", "to": "A8", "move_number": 15, "promotion": "Queen"}

After 3 invalid attempts → server forces a random legal move.

POST /resign

Resign from the game. Requires Bearer token.

curl -X POST http://localhost:8000/api/v1/resign \
  -H "Authorization: Bearer YOUR_TOKEN"
{"success": true, "game_status": "playing"}

POST /leave

Disconnect and replace with SmartBot. Token becomes invalid (410 on future requests).

curl -X POST http://localhost:8000/api/v1/leave \
  -H "Authorization: Bearer YOUR_TOKEN"
{"success": true, "message": "Игрок заменён SmartBot-ом"}

GET /my-game

Alias for /state. Returns 410 if player was replaced.

GET /games

List all active games. No auth required.

curl http://localhost:8000/api/v1/games
[{"game_id": "...", "status": "waiting", "players": [...], "move_number": 0}]

GET /board-geometry

Hex cell vertices for SVG rendering. No auth required.

WS /games/{game_id}/watch

WebSocket — subscribe to real-time game updates (read-only, no auth).

const ws = new WebSocket("ws://localhost:8000/api/v1/games/GAME_ID/watch");
ws.onmessage = (e) => {
  const msg = JSON.parse(e.data);
  // msg.type: "initial" | "move" | "resign"
  console.log(msg.type, msg.state);
};

Authentication

  1. POST /join → receive player_token.
  2. Include on all requests: Authorization: Bearer {token}.
  3. Token is a UUID, valid for the game's duration.

Error Codes

CodeMeaning
401Missing or invalid Bearer token
404Token not found in any game
409Not your turn / game not active / move_number mismatch
410Player was replaced by a bot
422Invalid/illegal move (includes legal_moves in response)
429Rate limit exceeded (check Retry-After header)
503Server at max capacity

Rate Limits

EndpointLimit
POST /join1 request per 10 seconds per IP
POST /move2 requests per second per token