maia3-chess-api / api-spec.md
anandu467's picture
Add tactical vision and game review endpoints
fa5dd4c
|
Raw
History Blame Contribute Delete
18.5 kB

Maia3 Chess API Specification

Base URL: https://<your-space>.hf.space

Authentication: All endpoints (except /api/health and GET /api/tactical-vision) require an x-api-key header.

x-api-key: sk-maia3-2026

Endpoints

Method Path Description
GET /api/health Health check
POST /api/bestmove Best move prediction
POST /api/analyze-move Analyze a specific move
POST /api/generate-puzzle Generate a tactical puzzle
GET /api/categories List puzzle categories
POST /api/tactical-vision Full tactical vision (model)
GET /api/tactical-vision Lightweight overlay (no model)
POST /api/game-review Post-game analysis

POST /api/tactical-vision

Real-time board overlay during a live game. Helps the human player see move probabilities, tactical threats, and danger assessment.

Request

{
  "fen": "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1",
  "elo_self": 1500,
  "elo_oppo": 1500,
  "top_n": 10,
  "player_color": "black",
  "bot_last_move": "e2e4",
  "compare_elos": true
}
Field Type Required Default Description
fen string yes FEN string of the current position
elo_self int no 1500 Player's Elo rating (0–5000)
elo_oppo int no 1500 Opponent's Elo rating (0–5000)
top_n int no 10 Number of top moves to return (1–20)
player_color string no "white" Player's side: "white" or "black"
bot_last_move string no null UCI of opponent's last move to analyze. Use the FEN from before the opponent's move for accurate analysis.
compare_elos bool no false Include Elo comparison across 1200/1500/1800/2100/2400

Response

{
  "fen": "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1",
  "elo_self": 1500,
  "elo_oppo": 1500,
  "player_side": "black",

  "position": {
    "win_probability": 0.4437,
    "eval_cp": -39,
    "confidence": "confusing",
    "entropy": 3.142,
    "max_probability": 0.425,
    "legal_move_count": 20,
    "danger_level": "low",
    "danger_detail": "Position is relatively straightforward."
  },

  "top_moves": [
    {
      "uci": "e7e5",
      "san": "e5",
      "probability": 0.4247,
      "rank": 1,
      "classification": "good",
      "result_eval_cp": 5,
      "result_win_probability": 0.5063,
      "eval_delta_cp": 44,
      "is_capture": false,
      "is_check": false,
      "is_mate": false,
      "is_tempting_blunder": false,
      "tactical_tags": []
    },
    {
      "uci": "e7e6",
      "san": "e6",
      "probability": 0.1220,
      "rank": 2,
      "classification": "mistake",
      "result_eval_cp": 1,
      "result_win_probability": 0.5013,
      "eval_delta_cp": 40,
      "is_capture": false,
      "is_check": false,
      "is_mate": false,
      "is_tempting_blunder": false,
      "tactical_tags": []
    }
  ],

  "threats": {
    "hanging_pieces": [],
    "attacked_pieces": [],
    "underdefended_squares": [],
    "king_safety_concern": false,
    "king_safety_detail": ""
  },

  "tactical_alerts": [
    {
      "type": "hanging_piece",
      "square": "e4",
      "piece": "pawn",
      "description": "Undefended white pawn on e4"
    }
  ],

  "bot_last_move": {
    "uci": "e2e4",
    "san": "e4",
    "probability": 0.5200,
    "rank": 1,
    "classification": "excellent"
  },

  "elo_comparison": {
    "1200": {
      "best_move": "e7e5",
      "best_probability": 0.4985,
      "top_moves": [
        { "uci": "e7e5", "san": "e5", "probability": 0.4985 },
        { "uci": "e7e6", "san": "e6", "probability": 0.1320 }
      ]
    },
    "1500": {
      "best_move": "e7e5",
      "best_probability": 0.4247,
      "top_moves": [
        { "uci": "e7e5", "san": "e5", "probability": 0.4247 }
      ]
    },
    "1800": {
      "best_move": "e7e5",
      "best_probability": 0.3875,
      "top_moves": [
        { "uci": "e7e5", "san": "e5", "probability": 0.3875 }
      ]
    },
    "2100": {
      "best_move": "e7e5",
      "best_probability": 0.3039,
      "top_moves": [
        { "uci": "e7e5", "san": "e5", "probability": 0.3039 }
      ]
    },
    "2400": {
      "best_move": "e7e5",
      "best_probability": 0.2654,
      "top_moves": [
        { "uci": "e7e5", "san": "e5", "probability": 0.2654 }
      ]
    }
  }
}

Field Reference

position

Field Type Description
win_probability float Maia3's predicted win probability for the side to move (0–1)
eval_cp int Centipawn evaluation derived from win probability
confidence string "clear" (one move dominates), "complex" (top move 50–85%), "confusing" (no clear favorite), "terminal" (game over)
entropy float Shannon entropy of the policy distribution over legal moves
max_probability float Probability of the top move
legal_move_count int Number of legal moves
danger_level string "low", "moderate", or "high" — how treacherous the position is
danger_detail string Human-readable explanation of the danger level

top_moves[]

Field Type Description
uci string Move in UCI format
san string Move in Standard Algebraic Notation
probability float Maia3's predicted probability a human at this Elo plays this move
rank int Rank among all legal moves (1 = most likely)
classification string "excellent" (≥60%), "good" (≥30%), "inaccuracy" (≥15%), "mistake" (≥5%), "blunder" (<5%)
result_eval_cp int Evaluation after playing this move (centipawns)
result_win_probability float Win probability after playing this move
eval_delta_cp int Change in evaluation: positive = improves position, negative = worsens
is_capture bool Whether the move is a capture
is_check bool Whether the move gives check
is_mate bool Whether the move delivers checkmate
is_tempting_blunder bool High probability (≥15%) but leads to a significantly worse position (eval_delta < -100cp)
tactical_tags string[] Tactical motifs detected: "fork", "pin", "skewer", "discovered_attack", "hanging_piece", "trapped_piece", "sacrifice", "zwischenzug", "king_safety"

threats

Field Type Description
hanging_pieces string[] Squares of opponent's undefended pieces
attacked_pieces string[] Squares of your attacked but undefended pieces
underdefended_squares string[] Squares where attacker value exceeds defender value
king_safety_concern bool Whether there's a king safety issue
king_safety_detail string Description of the king safety concern

tactical_alerts[]

Field Type Description
type string "hanging_piece", "attacked_piece", "in_check", "fork_opportunity"
square string Square name (e.g., "e4")
piece string Piece type (e.g., "pawn", "knight")
description string Human-readable description

bot_last_move

Only present when bot_last_move is provided in the request.

Field Type Description
uci string The move in UCI format
san string The move in SAN
probability float How likely Maia3 thought a human at this Elo would play this move
rank int Rank among all legal moves
classification string Move quality classification

elo_comparison

Only present when compare_elos: true. Keys are Elo levels (1200, 1500, 1800, 2100, 2400).

Field Type Description
best_move string Top move at this Elo
best_probability float Probability of the top move
top_moves array Top 5 moves at this Elo

GET /api/tactical-vision

Lightweight chess-only overlay — no model inference. Use for fast board overlays showing threats and tactical alerts.

Parameters

Parameter Type Required Default Description
fen string yes FEN string
player_color string no "white" Player's side

Response

{
  "fen": "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1",
  "player_side": "black",
  "threats": {
    "hanging_pieces": ["e4"],
    "attacked_pieces": [],
    "underdefended_squares": [],
    "king_safety_concern": false,
    "king_safety_detail": ""
  },
  "tactical_alerts": [
    {
      "type": "hanging_piece",
      "square": "e4",
      "piece": "pawn",
      "description": "Undefended white pawn on e4"
    }
  ],
  "board_info": {
    "turn": "black",
    "fullmove": 1,
    "halfmove_clock": 0,
    "is_check": false,
    "is_game_over": false,
    "piece_count": 31
  }
}

POST /api/game-review

Post-game analysis. Reviews every move in a completed game, calculates consistency, identifies blunder patterns, and provides recommendations.

Request

Provide either pgn or moves:

Option A: PGN

{
  "pgn": "[Event \"Casual\"]\n[White \"Player1\"]\n[Black \"Player2\"]\n[Result \"1-0\"]\n[WhiteElo \"1500\"]\n[BlackElo \"1480\"]\n\n1. e4 e5 2. Bc4 Nc6 3. Qh5 Nf6 4. Qxf7# 1-0",
  "elo_white": 1500,
  "elo_black": 1480
}

Option B: Move list

{
  "moves": ["e2e4", "e7e5", "f1c4", "b8c6", "d1h5", "g8f6", "h5f7"],
  "starting_fen": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
  "elo_white": 1500,
  "elo_black": 1500
}
Field Type Required Default Description
pgn string one of pgn/moves null PGN string of the game
moves string[] one of pgn/moves null List of UCI moves
starting_fen string no starting position Starting FEN
elo_white int no 1500 White player's Elo
elo_black int no 1500 Black player's Elo

Response

{
  "game_info": {
    "white": "Player1",
    "black": "Player2",
    "result": "1-0",
    "elo_white": 1500,
    "elo_black": 1480,
    "total_moves": 7,
    "opening": ""
  },

  "summary": {
    "consistency_score": 0.34,
    "consistency_label": "Below your usual level",
    "average_move_probability": 0.34,
    "blunder_count": 1,
    "mistake_count": 1,
    "inaccuracy_count": 2,
    "good_count": 1,
    "excellent_count": 2,
    "missed_opportunities": 0
  },

  "phase_breakdown": {
    "opening": {
      "moves": 7,
      "consistency_score": 0.34,
      "average_probability": 0.34,
      "blunders": 1,
      "mistakes": 1,
      "inaccuracies": 2,
      "good": 1,
      "excellent": 2,
      "label": "Opening technique needs work"
    },
    "middlegame": {
      "moves": 0,
      "consistency_score": 0.0,
      "average_probability": 0.0,
      "blunders": 0,
      "mistakes": 0,
      "inaccuracies": 0,
      "good": 0,
      "excellent": 0,
      "label": ""
    },
    "endgame": {
      "moves": 0,
      "consistency_score": 0.0,
      "average_probability": 0.0,
      "blunders": 0,
      "mistakes": 0,
      "inaccuracies": 0,
      "good": 0,
      "excellent": 0,
      "label": ""
    }
  },

  "moves": [
    {
      "move_number": 1,
      "side": "white",
      "uci": "e2e4",
      "san": "e4",
      "fen_before": "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
      "fen_after": "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1",
      "probability": 0.6400,
      "rank": 1,
      "classification": "excellent",
      "eval_before": 0,
      "eval_after": -18,
      "eval_delta": -18,
      "best_move": "e2e4",
      "best_move_probability": 0.6400,
      "is_capture": false,
      "is_check": false,
      "tactical_tags": [],
      "phase": "opening"
    }
  ],

  "blunder_genealogy": [
    {
      "blunder_move": 4,
      "root_cause_move": 2,
      "explanation": "The blunder at move 4 was likely caused by difficulties that started around move 2. The position became complex after Bc4."
    }
  ],

  "missed_opportunities": [
    {
      "move_number": 3,
      "side": "white",
      "played_move": "Qh5",
      "best_move": "Nf3",
      "eval_delta_missed": 150,
      "explanation": "Nf3 would have been much stronger, improving the position by 150 centipawns."
    }
  ],

  "danger_positions": [
    {
      "move_number": 3,
      "side": "black",
      "fen": "r1bqkbnr/pppp1ppp/2n5/4p3/2B1P3/8/PPPP1PPP/RNBQK1NR b KQkq - 1 3",
      "danger_level": "moderate",
      "danger_detail": "Position was complex with low probability for the played move.",
      "player_response": "Nf6 (inaccuracy)",
      "correct_response": "Qe7"
    }
  ],

  "eval_trajectory": [
    { "move": 1, "side": "white", "eval": -18 },
    { "move": 1, "side": "black", "eval": -5 },
    { "move": 2, "side": "white", "eval": -38 },
    { "move": 2, "side": "black", "eval": 52 },
    { "move": 3, "side": "white", "eval": -22 },
    { "move": 3, "side": "black", "eval": 493 },
    { "move": 4, "side": "white", "eval": 1000 }
  ],

  "tactical_patterns": {
    "missed_forks": 1,
    "missed_pins": 0,
    "missed_skewers": 0,
    "missed_discovered_attacks": 0,
    "hung_pieces": 0,
    "walked_into_tactics": 0,
    "most_common_mistake": "fork (1 occurrences)"
  },

  "recommendations": [
    "Focus on opening technique — your consistency drops significantly in openings",
    "Work on fork recognition — you missed opportunities to fork pieces",
    "Review your opening repertoire — low consistency suggests unfamiliar positions"
  ]
}

Field Reference

summary

Field Type Description
consistency_score float Average move probability across all moves (0–1)
consistency_label string Human-readable label: "Excellent performance", "Playing to your rating", "Below your usual level", "Significantly underperforming"
average_move_probability float Same as consistency_score
blunder_count int Number of blunders (<5% probability)
mistake_count int Number of mistakes (5–15%)
inaccuracy_count int Number of inaccuracies (15–30%)
good_count int Number of good moves (30–60%)
excellent_count int Number of excellent moves (≥60%)
missed_opportunities int Positions where eval dropped >100cp and a better move existed

phase_breakdown

Keys: "opening" (moves 1–10), "middlegame" (moves 11–30), "endgame" (move 31+ or ≤8 pieces).

Each phase has the same fields as summary plus a label describing performance.

moves[]

Field Type Description
move_number int Full move number
side string "white" or "black"
uci string Move in UCI format
san string Move in SAN
fen_before string FEN before the move
fen_after string FEN after the move
probability float Maia3's predicted probability
rank int Rank among legal moves
classification string Move quality
eval_before int Evaluation before the move (centipawns)
eval_after int Evaluation after the move (centipawns)
eval_delta int Change in evaluation
best_move string Maia3's top predicted move
best_move_probability float Probability of the best move
is_capture bool Whether the move is a capture
is_check bool Whether the move gives check
tactical_tags string[] Tactical motifs detected
phase string Game phase: "opening", "middlegame", "endgame"

blunder_genealogy[]

Traces each blunder back to its root cause.

Field Type Description
blunder_move int Move number of the blunder
root_cause_move int Move number where difficulties began
explanation string Human-readable explanation

missed_opportunities[]

Field Type Description
move_number int Move number
side string "white" or "black"
played_move string SAN of the played move
best_move string UCI of the better move
eval_delta_missed int Centipawns lost by not playing the best move
explanation string Human-readable explanation

danger_positions[]

Field Type Description
move_number int Move number
side string "white" or "black"
fen string FEN of the dangerous position
danger_level string "high" or "moderate"
danger_detail string Description of the danger
player_response string What the player played (with classification)
correct_response string The better move

eval_trajectory[]

Field Type Description
move int Move number
side string "white" or "black"
eval int Evaluation in centipawns after the move

tactical_patterns

Field Type Description
missed_forks int Number of missed fork opportunities
missed_pins int Number of missed pins
missed_skewers int Number of missed skewers
missed_discovered_attacks int Number of missed discovered attacks
hung_pieces int Number of times a piece was hung
walked_into_tactics int Number of times the player walked into a tactic
most_common_mistake string Description of the most frequent mistake type

recommendations

Array of strings with actionable improvement suggestions based on the analysis.


Error Responses

All endpoints return errors in this format:

{
  "error": "Description of the error"
}
Status Code Meaning
400 Bad request (invalid FEN, missing fields, invalid move)
401 Unauthorized (missing or invalid API key)
405 Method not allowed
500 Internal server error
503 Model unavailable (still loading or failed)