---
title: "Analyze a complete chess game"
method: POST
path: "/analyze_game"
tags: ["Analysis"]
---

# Analyze a complete chess game

`POST /analyze_game`

Analyze a complete chess game from PGN.

**What you get:**
- Move-by-move evaluation with error classification (blunder/mistake/inaccuracy)
- Per-side phase summaries (opening/middlegame/endgame for White AND Black)
- Mistakes separated by side with best move alternatives
- Expandable overview bullet points and a 4-category study plan
  (opening/tactics/strategy/endgame)
- Turning points with phase context
- Natural language game narrative

**Per-move data** (for eval charts, board overlays, move arrows):
evaluation_before, best_move_uci, fen_before, fen_after, coaching_text.

## Request body

- AnalyzeGameEndpointRequest
  - `pgn` string, required — Full PGN game text with moves
  - `question` string, nullable — User's question about the game. Partner-tier contracts only — ignored on standard API keys.
  - `personality` string — Coaching personality: 'Coach', 'Grandmaster Chessy', 'Hustler Chessy', 'Roasty Chessy'
  - `player_color` string, nullable — Focus analysis on this player: 'white' or 'black'
  - `user_stats` object, nullable — User context (rating, recent performance) for personalized coaching
  - `model` string, nullable — Coaching model override. Partner-tier contracts only — ignored on standard API keys.
  - `classify_intent` boolean — Classify user's question intent for better response generation
  - `include_all_moves` boolean — Include all moves (true) or just errors (false)
  - `detect_motifs` boolean — Detect tactical motifs (forks, pins, hanging pieces)
  - `output_format` 'structured' | 'narrative' | 'both' — Response format: 'structured' (JSON), 'narrative' (text), or 'both'
  - `detail_level` 'brief' | 'standard' | 'detailed' — Verbosity level of response
  - `coaching_style` 'encouraging' | 'direct' | 'socratic' — Coaching tone
  - `skill_level` 'beginner' | 'intermediate' | 'advanced' — Player skill level for tailored explanations
  - `include_variations` boolean — Include move variations in response
  - `max_moves_analyzed` integer, nullable — Limit number of moves analyzed (null = all moves)
  - `language` string — Response language code (ISO 639-1)
  - `player_rating` integer, nullable — Player rating (e.g. 1200) for rating-adjusted explanations
  - `include_debug` boolean — Internal use — ignored on customer API keys
  - `reasoning_effort` 'none' | 'minimal' | 'low' | 'medium' | 'high', nullable — Reasoning effort for LLM coaching. 'none' disables reasoning entirely (fastest). Default: 'minimal'.
  - `max_tokens` integer, nullable — Max output tokens for LLM coaching response. Clamped to 256-4000.
  - `position_analysis_scope` string, nullable — Which moves get deep positional analysis: 'key' (errors + big eval swings, default), 'none' (skip), or 'all' (every move — partner-tier contracts only).
  - `per_move_coaching` boolean — Generate LLM coaching commentary per analyzed move. Each move gets a 1-3 sentence coaching comment. Runs in parallel with narrative generation (~3% overhead).

## Response `200`

Structured game review. Per-move evaluations are pawn-unit floats (White's perspective) and are null on terminal plies — distinct from /analyze_position's integer centipawns.

- GameAnalysisResponse — Success response for ``POST /analyze_game``. A structured game review: a natural-language narrative plus per-side mistakes, turning points, a study plan, tactical-theme tallies, a win-probability curve, and a simplified per-move list for charts and board overlays. Note on evaluations: per-move evaluations here are pawn-unit floats and are null on terminal plies — unlike ``/analyze_position``'s integer centipawns with the ±10000 mate sentinel.
  - `overview` GameOverview — High-level game summary: result, opening, and per-phase prose.
    - `result` string, nullable — Game result: 'white', 'black', or 'draw'.
    - `opening_name` string, nullable — Named opening/variation identified for the game.
    - `summary_sentence` string, nullable — One-sentence summary of how the game was decided.
    - `overview_bullets` string[] — Expandable bullet points walking through the key moments.
    - `white_opening` string, nullable — Prose on White's opening play. May be empty when the game did not reach the phase.
    - `black_opening` string, nullable — Prose on Black's opening play. May be empty.
    - `white_middlegame` string, nullable — Prose on White's middlegame play. May be empty.
    - `black_middlegame` string, nullable — Prose on Black's middlegame play. May be empty.
    - `white_endgame` string, nullable — Prose on White's endgame play. May be empty.
    - `black_endgame` string, nullable — Prose on Black's endgame play. May be empty.
    - `narrative_text` string, nullable — Full natural-language narrative of the game (same content as the top-level 'response').
  - `turning_points` GameTurningPoint[] — Moments where the balance shifted.
    - `ply` integer, required — Half-move number (1-based) at which the shift occurred.
    - `move` string, required — The move played, in Standard Algebraic Notation.
    - `phase` string, nullable — Game phase: 'opening', 'middlegame', or 'endgame'.
    - `swing_pp` number, nullable — Size of the win-probability swing, in percentage points.
    - `explanation` string, nullable — Why this move mattered.
    - `move_category` string, nullable — Move quality label (e.g. 'mistake', 'good', 'excellent', 'blunder', 'inaccuracy', 'book').
  - `white_mistakes` GameMistake[] — White's errors with recommended alternatives.
    - `ply` integer, required — Half-move number (1-based) of the error.
    - `move` string, required — The move played, in Standard Algebraic Notation.
    - `swing_pp` number, nullable — Win-probability lost by the move, in percentage points.
    - `why` string, nullable — Explanation of what went wrong and the idea behind the better move.
    - `move_category` string, nullable — Error severity label (e.g. 'inaccuracy', 'mistake', 'blunder').
    - `better_move` string, nullable — The recommended move, in Standard Algebraic Notation.
  - `black_mistakes` GameMistake[] — Black's errors with recommended alternatives.
    - `ply` integer, required — Half-move number (1-based) of the error.
    - `move` string, required — The move played, in Standard Algebraic Notation.
    - `swing_pp` number, nullable — Win-probability lost by the move, in percentage points.
    - `why` string, nullable — Explanation of what went wrong and the idea behind the better move.
    - `move_category` string, nullable — Error severity label (e.g. 'inaccuracy', 'mistake', 'blunder').
    - `better_move` string, nullable — The recommended move, in Standard Algebraic Notation.
  - `errors` GameMistake[] — Combined error list across both sides.
    - `ply` integer, required — Half-move number (1-based) of the error.
    - `move` string, required — The move played, in Standard Algebraic Notation.
    - `swing_pp` number, nullable — Win-probability lost by the move, in percentage points.
    - `why` string, nullable — Explanation of what went wrong and the idea behind the better move.
    - `move_category` string, nullable — Error severity label (e.g. 'inaccuracy', 'mistake', 'blunder').
    - `better_move` string, nullable — The recommended move, in Standard Algebraic Notation.
  - `white_best_move` GameBestMove — The single strongest move a side found in the game.
    - `ply` integer, required — Half-move number (1-based) of the move.
    - `move` string, required — The move played, in Standard Algebraic Notation.
    - `swing_pp` number, nullable — Win-probability gained by the move, in percentage points.
    - `why` string, nullable — Why the move was strong.
    - `move_category` string, nullable — Move quality label.
  - `black_best_move` GameBestMove — The single strongest move a side found in the game.
    - `ply` integer, required — Half-move number (1-based) of the move.
    - `move` string, required — The move played, in Standard Algebraic Notation.
    - `swing_pp` number, nullable — Win-probability gained by the move, in percentage points.
    - `why` string, nullable — Why the move was strong.
    - `move_category` string, nullable — Move quality label.
  - `study_plan` GameStudyPlan — A four-part training plan tailored to one player's game.
    - `for_color` string, nullable — Which side the plan is written for: 'white' or 'black'.
    - `strengths` string[] — What the player did well.
    - `weaknesses` string[] — Areas to work on.
    - `opening_work` string, nullable — Opening-phase study recommendation.
    - `tactics_work` string, nullable — Tactics study recommendation.
    - `strategic_work` string, nullable — Strategy/planning study recommendation.
    - `endgame_work` string, nullable — Endgame study recommendation.
  - `response` string, required — Full natural-language narrative of the game.
  - `tactical_themes` GameTacticalThemes — Tactical motif tally across the whole game.
    - `themes` object — Map of theme name (e.g. 'pin', 'fork', 'skewer') to its per-side counts.
    - `total_motifs` integer — Total tactical motifs detected in the game.
  - `momentum` GameMomentum — Win-probability trajectory and notable momentum shifts.
    - `momentum_events` object[] — Notable swings in momentum during the game.
    - `wp_curve` WinProbabilityPoint[] — Per-ply win-probability curve for charting the game's flow.
      - `ply` integer, required — Half-move number (1-based).
      - `wp_white` number, required — White's win probability at this ply, as a percentage (0-100).
  - `opening_deviation` GameOpeningDeviation — Where each side departed from opening theory.
    - `white_deviation` OpeningDeviationSide — The first ply at which a side left the recommended opening line.
      - `ply` integer, required — Half-move number (1-based) of the deviation.
      - `move` string, required — The move played, in Standard Algebraic Notation.
      - `engine_preferred` string, nullable — The recommended move at that point, in Standard Algebraic Notation.
    - `black_deviation` OpeningDeviationSide — The first ply at which a side left the recommended opening line.
      - `ply` integer, required — Half-move number (1-based) of the deviation.
      - `move` string, required — The move played, in Standard Algebraic Notation.
      - `engine_preferred` string, nullable — The recommended move at that point, in Standard Algebraic Notation.
    - `opening_violations` string[] — Human-readable opening-principle violations detected.
  - `accuracy_context` GameAccuracyContext — Per-side accuracy scores for the game.
    - `white` AccuracySide — Overall accuracy score for one side.
      - `accuracy` number, nullable — Accuracy percentage (0-100) for the side.
    - `black` AccuracySide — Overall accuracy score for one side.
      - `accuracy` number, nullable — Accuracy percentage (0-100) for the side.
  - `critical_lines` object[] — Key forcing lines worth studying, when detected.
  - `piece_activity` GamePieceActivity — Standout pieces of the game, per side.
    - `star_piece` PieceBySide — A named piece for each side.
      - `white` string, nullable — Piece name for White (e.g. 'Queen').
      - `black` string, nullable — Piece name for Black.
    - `worst_piece` PieceBySide — A named piece for each side.
      - `white` string, nullable — Piece name for White (e.g. 'Queen').
      - `black` string, nullable — Piece name for Black.
  - `game_summary` GameSummary — Basic game metadata and accuracy stats.
    - `result` string, nullable — Result string in PGN form (e.g. '1-0', '0-1', '1/2-1/2').
    - `opening` string, nullable — Named opening.
    - `eco` string, nullable — ECO opening code, when identified. May be null even with a named opening.
    - `total_moves` integer, nullable — Total half-moves (plies) in the game.
    - `white_accuracy` number, nullable — White accuracy percentage (0-100).
    - `black_accuracy` number, nullable — Black accuracy percentage (0-100).
  - `moves` GameMove[] — Per-move review list for eval charts, board overlays, and move arrows.
    - `move_number` integer, nullable — Full-move number (1-based).
    - `ply` integer, nullable — Half-move number (1-based).
    - `move` string, nullable — The move in Standard Algebraic Notation.
    - `color` string, nullable — Side to move: 'white' or 'black'.
    - `classification` string, nullable — Move quality label (e.g. 'book', 'good', 'excellent', 'inaccuracy', 'mistake', 'blunder').
    - `evaluation_before` number, nullable — Evaluation in pawns before the move (White's perspective). Null on terminal plies.
    - `evaluation_after` number, nullable — Evaluation in pawns after the move (White's perspective). Null on terminal plies (e.g. the mating move).
    - `best_move` string, nullable — Recommended move in Standard Algebraic Notation, when a better move existed.
    - `best_move_uci` string, nullable — Recommended move in UCI coordinate notation, when available.
    - `fen_before` string, nullable — Position before the move, in Forsyth-Edwards Notation.
    - `fen_after` string, nullable — Position after the move, in Forsyth-Edwards Notation.
    - `review_text` string, nullable — Short factual annotation of the move.
    - `coaching_text` string, nullable — Deeper coaching prose for the move. Populated on notable moves; null otherwise.
    - `game_phase` string, nullable — Game phase: 'opening', 'middlegame', or 'endgame'.
    - `best_move_explanation` string, nullable — Explanation of the recommended move, when available.
    - `expected_points_before` number, nullable — Expected points (0-1) before the move, when available.
    - `expected_points_after` number, nullable — Expected points (0-1) after the move, when available.
    - `expected_points_lost` number, nullable — Expected points lost by the move, when available.
  - `phases` object, nullable — Per-phase summaries, when the analysis pipeline produces them.
  - `narrative` string, nullable — Legacy narrative field emitted by some analysis paths; prefer overview.narrative_text.

## Other responses

- `422` — Validation Error

## Changes

- **2026-07-26** `99acef68ca57` — 1 breaking, 20 info
  - the response's body type/format changed from ``/`` to `object`/`` for status `200`
  - the `personality` request property default value changed from `Coach` to `Grandmaster Chessy`
  - added the optional property `accuracy_context` to the response with the `200` status
  - added the optional property `black_best_move` to the response with the `200` status
  - …17 more

[Change history](https://skmtc.dev/chessvia/apis/chessvia-analysis-api/changes/analyze_game/post.md)

---

[API](https://skmtc.dev/chessvia/apis/chessvia-analysis-api.md) · [All operations](https://skmtc.dev/chessvia/apis/chessvia-analysis-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/chessvia/chessvia-analysis-api/revisions/99acef68ca57/schema)
