API Reference

Complete endpoint documentation for the ChessGrammar API v1.

Base URLs

  • Free tier: https://chessgrammar.com/api/v1
  • Paid tiers (Builder, Scale): https://api.chessgrammar.com/v1

Authentication

The free tier is unauthenticated and rate-limited per IP (30 req/min). Paid tiers require an API key sent in the Authorization header:

Authorization: Bearer cg_YOUR_API_KEY

See Limits & Access for plan details and how to obtain a key.


POST /extract

Analyze a single position (FEN) for tactical patterns.

Request

{
  "fen": "6k1/5p1p/4p3/4q3/3n4/2Q3P1/PP1N1P1P/6K1 b - - 3 37",
  "patterns": ["fork", "pin"],
  "depth": "l2",
  "with_sequence": true
}

Parameters:

ParameterTypeRequiredDefaultDescription
fenstringyesValid FEN string
patternsstring[]noall 10Filter by pattern names
depthstringno"l2""l1" (fast scan) or "l2" (forcing tree confirmation)
with_sequencebooleannofalseInclude forcing move sequences (~205ms/tactic). Ignored when depth="l1".

Response

{
  "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/..."
}

Tactic object

FieldTypeDescription
patternstringTactic type (fork, pin, skewer, discovered_attack, double_check, back_rank_mate, smothered_mate, deflection, interference, trapped_piece)
colorstringSide with the tactic (white or black)
trigger_movestringInitiating move in UCI format
key_squaresstring[]Critical squares involved
target_squaresstring[]Attacked/affected piece squares
targetsobject[]Detailed target info (square, piece, piece_name, color)
gainintegerMaterial gain in centipawns
gain_confirmedbooleantrue if confirmed via forcing tree (L2)
is_matebooleantrue if tactic leads to checkmate
sequencestring[] or nullForcing moves in UCI format (when with_sequence: true)
fenstringPosition 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


POST /extract_game

Analyze a complete game (PGN) for tactical patterns across every position.

Request

{
  "pgn": "1. e4 e5 2. Nf3 Nc6 3. Bc4 ...",
  "mode": "played",
  "patterns": ["fork", "discovered_attack"],
  "depth": "l2",
  "with_sequence": false
}

Parameters:

ParameterTypeRequiredDefaultDescription
pgnstringyesPGN string of a complete game
modestringno"played""played" (tactics actually executed) or "available" (all tactical opportunities)
patternsstring[]noall 10Filter by pattern names
depthstringno"l2""l1" (fast scan) or "l2" (forcing tree confirmation)
with_sequencebooleannofalseInclude forcing move sequences. Ignored when depth="l1".

Response

Same tactic structure as /extract, with additional per-tactic fields:

FieldDescription
plyHalf-move number in the game
status"played" or "existing" (in mode: "played" only)

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

StatusBodyCause
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
401"error": "Missing or invalid API key"Paid endpoint called without a valid Authorization: Bearer header
429"error": "Rate limit exceeded"Plan rate limit exceeded — see Limits