OllinDocs
API reference

Preflop endpoints

Catalog, depth packs, node documents, and the boundaries bridge — with real responses.

The preflop tier serves one pack per stack depth (see Preflop Pack v1). Depths accept 10 or 10bb. Examples are real responses against the trimmed real fixtures.

GET /v1/preflop

The catalog: every available depth with its tree size and coverage summary.

GET /v1/preflop → 200
{
  "schema_version": 1,
  "campaign": "berserk_v1",
  "stamp": "20260721T131354Z",
  "tier": "preflop-v0",
  "format": "MTT",
  "metric": "ChipEV",
  "table_size": 8,
  "seats": ["UTG", "UTG1", "LJ", "HJ", "CO", "BTN", "SB", "BB"],
  "depths": [
    {
      "depth_bb": 10,
      "node_count": 2573,
      "boundary_count": 989,
      "covered_boundaries": 1,
      "settings": {
        "format": "MTT", "metric": "ChipEV", "table_size": 8,
        "bb_chips": 100, "sb_bb": 0.5, "ante_bb": 0.12,
        "stack_bb": 10, "solver": "HRC"
      }
    },
    { "depth_bb": 15, "…": "…" }
  ]
}

covered_boundaries counts boundaries with coverage served or solved — the number the Study screen can bridge (or will bridge next) at that depth.

GET /v1/preflop/:depth

The root node plus the compact tree index — enough to render the landing and lazily walk the tree via the node endpoint.

GET /v1/preflop/10 → 200
{
  "schema_version": 1,
  "depth_bb": 10,
  "settings": { "…": "…" },
  "seats": ["UTG", "UTG1", "LJ", "HJ", "CO", "BTN", "SB", "BB"],
  "node_count": 2573,
  "boundary_count": 989,
  "root": {
    "node_path": "root",
    "node_id": 0,
    "seat_to_act": "UTG",
    "actions": [
      { "id": "fold", "kind": "fold", "next": { "type": "node", "node_path": "root-fold" } },
      { "id": "call", "kind": "call", "size_bb": 1, "next": { "type": "node", "node_path": "root-call" } },
      { "id": "r2", "kind": "raise", "size_bb": 2, "next": { "type": "node", "node_path": "root-r2" } },
      { "id": "allin", "kind": "allin", "size_bb": 9.88, "is_all_in": true, "next": { "type": "node", "node_path": "root-allin" } }
    ],
    "strategy169": { "AA": [0, 0.9637, 0.0363, 0], "A2o": [1, 0, 0, 0], "…": "all 169 keys" },
    "range169": { "…": "sparse — 169 keys at root" },
    "pot_bb": 2.46,
    "facing_bb": 1,
    "stacks_bb": [9.88, 9.88, 9.88, 9.88, 9.88, 9.88, 9.38, 8.88],
    "active_seats": ["UTG", "UTG1", "LJ", "HJ", "CO", "BTN", "SB", "BB"],
    "players_remaining": 8
  },
  "index": [
    { "path": "root", "seat": 0, "n_actions": 4 },
    { "…": "2572 more entries" }
  ],
  "meta": {
    "campaign": "berserk_v1", "stamp": "20260721T131354Z", "tier": "preflop-v0",
    "generator": "extract_preflop_v0.py",
    "generated_at": "2026-07-24T14:16:33.675847+00:00",
    "source_files": ["10BB.zip", "10BB.hrcz"]
  }
}

Note the ante arithmetic in the root: pot 2.46 = SB 0.5 + BB 1 + 8 × 0.12 ante; stacks already net of posts (9.88 = 10 − 0.12, SB 9.38, BB 8.88).

GET /v1/preflop/:depth/node

One node by path (path defaults to root). The response inlines every boundary document this node's actions point at, so terminal leaves render without a second request.

GET /v1/preflop/10/node?path=root-fold-fold-fold-fold-fold-r2 → 200
{
  "schema_version": 1,
  "depth_bb": 10,
  "node": {
    "node_path": "root-fold-fold-fold-fold-fold-r2",
    "seat_to_act": "SB",
    "actions": [
      { "id": "fold", "kind": "fold", "next": { "type": "node", "node_path": "root-fold-fold-fold-fold-fold-r2-fold" } },
      { "id": "call", "kind": "call", "size_bb": 1.5, "next": { "type": "node", "node_path": "root-fold-fold-fold-fold-fold-r2-call" } },
      { "id": "allin", "kind": "allin", "size_bb": 9.88, "is_all_in": true, "next": { "type": "node", "node_path": "root-fold-fold-fold-fold-fold-r2-allin" } }
    ],
    "…": "strategy169 / range169 / pot_bb / stacks_bb as in the contract"
  },
  "boundaries": {}
}

Unknown paths return 404 NODE_NOT_FOUND with the depth's node_count and root_path in the details.

GET /v1/preflop/:depth/boundaries

The complete HU → postflop-family bridge for a depth, with coverage counts.

GET /v1/preflop/10/boundaries → 200
{
  "schema_version": 1,
  "depth_bb": 10,
  "count": 989,
  "coverage_counts": { "none": 988, "served": 1 },
  "boundaries": [
    {
      "node_path": "root-fold-fold-fold-fold-fold-r2-fold",
      "action_id": "call",
      "kind": "flop_hu",
      "line": "srp_btn_bb",
      "oop": "BB",
      "ip": "BTN",
      "pot_bb": 5.46,
      "eff_bb": 7.88,
      "family_id": "10bb_srp_btn_bb_p7v5_n21",
      "coverage": "served",
      "solved_boards": 184
    },
    {
      "node_path": "root-call-r2-allin-call-fold",
      "action_id": "fold",
      "kind": "showdown_allin",
      "line": "3bet_call",
      "oop": "LJ",
      "ip": "HJ",
      "pot_bb": 25.22,
      "eff_bb": 0,
      "family_id": null,
      "coverage": "none"
    },
    { "…": "987 more" }
  ]
}

The coverage semantics and their UI treatment are documented in the bridge guide.

On this page