API Reference
Complete endpoint documentation for the ChessGrammar API v1.
Base URL: https://chessgrammar.com/api/v1
Access
The API is in Developer Preview. No authentication is required:
- 30 requests/minute per IP
- 3 game analyses/day per IP (position analysis is unlimited within the rate limit)
Need higher limits? Get in touch.
POST /extract
Analyze a position (FEN) or a game (PGN) for tactical patterns.
FEN Request
{
"fen": "6k1/5p1p/4p3/4q3/3n4/2Q3P1/PP1N1P1P/6K1 b - - 3 37",
"patterns": ["fork", "pin"],
"depth": "l2",
"with_sequence": true
}
Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
fen | string | yes | — | Valid FEN string |
patterns | string[] | no | all 10 | Filter by pattern names |
depth | string | no | "l2" | "l1" (fast scan) or "l2" (forcing tree confirmation) |
with_sequence | boolean | no | false | Include forcing move sequences (~205ms/tactic). Ignored when depth="l1". |
PGN Request
{
"pgn": "1. e4 e5 2. Nf3 Nc6 3. Bc4 ...",
"mode": "played",
"patterns": ["fork", "discovered_attack"],
"with_sequence": false
}
Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pgn | string | yes | — | PGN string of a complete game |
mode | string | no | "played" | "played" (tactics actually executed) or "available" (all tactical opportunities) |
patterns | string[] | no | all 10 | Filter by pattern names |
depth | string | no | "l2" | "l1" or "l2" |
with_sequence | boolean | no | false | Include forcing move sequences. Ignored when depth="l1". |
Response (FEN)
{
"tactics": [
{
"pattern": "fork",
"color": "black",
"key_squares": ["e2"],
"target_squares": ["g1", "c3"],
"targets": [
{"square": "g1", "piece": "K", "piece_name": "king", "color": "white"},
{"square": "c3", "piece": "Q", "piece_name": "queen", "color": "white"}
],
"gain": 700,
"gain_confirmed": true,
"is_mate": false,
"trigger_move": "d4e2",
"sequence": ["d4e2", "g1g2", "e2c3", "b2c3"],
"fen": "6k1/5p1p/..."
}
],
"count": 1,
"depth": "l2",
"performance_ms": 48.2,
"fen": "6k1/5p1p/..."
}
Response (PGN)
Same structure as FEN response, with additional fields per tactic:
| Field | Description |
|---|---|
ply | Half-move number in the game |
status | "played" or "existing" (in mode: "played" only) |
Tactic object
| Field | Type | Description |
|---|---|---|
pattern | string | Tactic type (fork, pin, skewer, discovered_attack, double_check, back_rank_mate, smothered_mate, deflection, interference, trapped_piece) |
color | string | Side with the tactic (white or black) |
trigger_move | string | Initiating move in UCI format |
key_squares | string[] | Critical squares involved |
target_squares | string[] | Attacked/affected piece squares |
targets | object[] | Detailed target info (square, piece, piece_name, color) |
gain | integer | Material gain in centipawns |
gain_confirmed | boolean | true if confirmed via forcing tree (L2) |
is_mate | boolean | true if tactic leads to checkmate |
sequence | string[] or null | Forcing moves in UCI format (when with_sequence: true) |
fen | string | Position FEN |
Pattern names
Valid values for the patterns filter:
fork, pin, skewer, discovered_attack, double_check, back_rank_mate, smothered_mate, deflection, interference, trapped_piece
GET /health
Returns service status and engine info.
curl https://chessgrammar.com/api/v1/health
{
"status": "ok",
"engine_version": "2.5",
"api_version": "1.0",
"patterns": ["fork", "pin", "skewer", "discovered_attack", "double_check", "back_rank_mate", "smothered_mate", "deflection", "interference", "trapped_piece"],
"patterns_count": 10
}
Errors
| Status | Body | Cause |
|---|---|---|
| 400 | "error": "Missing 'fen' or 'pgn' field" | No input provided |
| 400 | "error": "Invalid FEN" | Malformed FEN string |
| 400 | "error": "Invalid PGN" | Malformed PGN |
| 400 | "error": "Invalid pattern: xyz" | Unknown pattern name in filter |
| 429 | "error": "Rate limit exceeded" | More than 30 requests/minute |
| 429 | "error": "Daily game analysis limit reached. Need more? Contact us." | More than 3 game analyses/day |