---
title: "Analyze a chess position"
method: POST
path: "/analyze_position"
tags: ["Analysis"]
---

# Analyze a chess position

`POST /analyze_position`

Analyze a chess position with Stockfish + coaching response.

**Main use cases:**
- Live game analysis - Get best move suggestions during games
- Board evaluation - Show position assessment to users
- Q&A bot - Answer user questions about positions

**What you get:**
- Stockfish evaluation in centipawns
- Best move recommendation
- Categorical position assessment (equal, slight advantage, winning, etc.)
- Natural language coaching response

**Response fields:** response, fen, best_move, best_move_uci, evaluation, assessment

**Example request:**
```json
{
  "position": "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1",
  "question": "What should I play?",
  "skill_level": "intermediate"
}
```

## Request body

- AnalyzePositionRequest
  - `position` string, required — Position in FEN notation or PGN moves
  - `question` string, nullable — User's question about the position
  - `personality` string — Coaching personality: 'Coach', 'Grandmaster Chessy', 'Hustler Chessy', 'Roasty Chessy'
  - `last_move` string, nullable — Last move played in SAN notation (for tactical context)
  - `user_stats` object, nullable — User context (rating, recent performance) for personalized coaching
  - `history` unknown[], nullable — Optional prior conversation turns [{role:'user'|'assistant', content}] for follow-up coherence. Fully lenient (List[Any]) — non-dict / wrong-role / empty entries are filtered at runtime, never rejected at validation. Ignored when absent — no change to existing single-turn behavior.
    - unknown
  - `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
  - `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
  - `include_stockfish` boolean — Run Stockfish engine analysis
  - `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 — values below 256 truncate coaching mid-sentence because the model's internal reasoning consumes part of the budget.

## Response `200`

Position analysis with coaching. Evaluation is integer centipawns (White's perspective); forced mate uses the ±10000 sentinel.

- PositionAnalysisResponse — Success response for ``POST /analyze_position``. A compact, six-field shape: coaching prose plus the machine-readable fields needed to draw a best-move arrow and an evaluation bar. Evaluation convention: ``evaluation`` is an integer in centipawns from White's point of view (positive favours White). A forced mate is reported with the sentinel ``+10000`` / ``-10000`` rather than a numeric distance; the mate distance, when known, is stated in ``response``. (On ``/analyze_game`` the per-move evaluations are pawn-unit floats instead — see ``GameMove.evaluation_before``.)
  - `response` string, required — Natural-language coaching for the position: the best plan and why it works.
  - `fen` string, required — The analysed position in Forsyth-Edwards Notation (echoed from the request).
  - `best_move` string, nullable — Best move in Standard Algebraic Notation (e.g. 'Nxe5'). Null when the position is terminal (checkmate/stalemate).
  - `best_move_uci` string, nullable — Best move in UCI coordinate notation (e.g. 'f3e5'), for drawing arrows on a board. Null on terminal positions.
  - `evaluation` integer, nullable — Position evaluation in centipawns from White's perspective (positive favours White). A forced mate returns the sentinel +10000 or -10000 (no numeric mate distance). Null on terminal positions.
  - `assessment` string, required — Categorical read of the evaluation: one of equal, slight_white, slight_black, winning_white, winning_black, decisive_white, decisive_black, or unknown.

## Other responses

- `422` — Validation Error

## Changes

- **2026-07-26** `99acef68ca57` — 1 breaking, 7 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 `best_move` to the response with the `200` status
  - added the optional property `best_move_uci` to the response with the `200` status
  - …4 more

[Change history](https://skmtc.dev/chessvia/apis/chessvia-analysis-api/changes/analyze_position/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)
