Postflop endpoints
The family catalog, family detail, board NodeDocuments, and the 501 tree slot — with real responses.
All examples below are real responses from the API serving the trimmed
real-producer fixtures (fixtures-real/), elided (…) for length. One
adjustment: the fixtures trim each family to 2 boards, so board_count and
the boards list are restored here to their production value (184).
GET /v1/families
The postflop catalog — one summary per family the serving tier currently
carries. In the GCS layout the list refreshes as the extraction ETL uploads
packs (on MANIFEST_TTL_MS, both on access and via a background interval).
{
"campaign": "berserk_v1",
"stamp": "20260721T131354Z",
"tier": "v0-roots",
"families": [
{
"id": "100bb_3bet_call_p7v5_n13380",
"depth_bb": 100,
"line": "3bet_call",
"positions": { "oop": "p7", "ip": "p5" },
"pot_bb": 51.6943,
"eff_bb": 100,
"tier": "root",
"board_count": 184
},
{ "id": "100bb_4bet_call_p7v5_n13443", "…": "…" }
]
}positions uses HRC seat indices (p7 = BB, p5 = BTN). The family id is
the arriving-library slug: {depth}bb_{line}_p{oop}v{ip}_n{hrcNodeId}.
GET /v1/families/:fam
Family detail: solve config, preflop ranges, and the board index.
{
"family": { "id": "100bb_3bet_call_p7v5_n13380", "depth_bb": 100, "…": "…" },
"config": {
"bet_sizes_pct": [25, 55, 80, 125],
"raise_sizes_pct": [55],
"accuracy_target_pct_pot": 0.3,
"solver": "solve_config=tiny via extract_roots_v0.py"
},
"ranges": { "oop": { "AhAd": 1, "…": "…" }, "ip": { "…": "…" } },
"boards": ["2s2h2d", "…", "Ks7s6s"],
"notes": [
"family preflop range weights are unavailable in sealed root data — served membership-only (uniform weight 1)",
"per-board IP range weights are unavailable — served uniform; documents carry meta.ip_weights_uniform=true",
"bb values derived with bb_chips = eff_stack_chips / depth_bb (meta.bb_chips_derived=true); effective_stack_bb === depth_bb by construction"
]
}notes (optional) is where the v0 adapter states its caveats in prose — the
same facts the per-board documents carry as
v1.1 meta flags.
GET /v1/families/:fam/boards/:flop
The full NodeDocument v1 for the board's root node. Board ids are
normalized (ks7s6s → Ks7s6s).
{
"schema_version": 1,
"family_id": "100bb_3bet_call_p7v5_n13380",
"board": "Ks7s6s",
"node_path": "root",
"street": "flop",
"actor": "oop",
"pot_bb": 51.6943,
"effective_stack_bb": 100,
"actions": [
{ "id": "check", "kind": "check" },
{ "id": "bet_25", "kind": "bet", "amount_bb": 12.9236, "fraction_pot": 0.25 },
{ "id": "bet_55", "kind": "bet", "amount_bb": 28.4319, "fraction_pot": 0.55 },
{ "id": "bet_80", "kind": "bet", "amount_bb": 41.3554, "fraction_pot": 0.8 },
{ "id": "bet_125", "kind": "bet", "amount_bb": 64.6179, "fraction_pot": 1.25 },
{ "id": "allin", "kind": "allin", "amount_bb": 100, "fraction_pot": 1.93445 }
],
"ranges": {
"oop": { "4c3c": 0.0682, "…": "…" },
"ip": { "5c4c": 1, "…": "…" }
},
"strategy": { "4c3c": [0, 0.998825, 0.001175, 0, 0, 0], "…": "…" },
"evs": { "4c3c": [14.8319, 15.5388, 14.9497, 12.4406, 4.6278, -0.1049], "…": "…" },
"evs_current": { "4c3c": 15.5381, "…": "…" },
"grid169": [
{
"class": "AA", "row": 0, "col": 0, "weight": 6,
"strategy": [0.021477, 0.941234, 0.035977, 0.001312, 0, 0],
"ev": [47.0729, 47.3414, 47.1934, 47.0528, 46.6779, 46.2034]
},
{ "…": "168 more cells, row-major" }
],
"exploitability": { "exploitability_bb": 0.1464, "exploitability_pct_pot": 0.2832 },
"meta": {
"campaign": "berserk_v1",
"stamp": "20260721T131354Z",
"tier": "root",
"pack_sha256": "38b207591014bfb929478985269e04643814ff5bbef9d958b927f0530b0bdc13",
"solver": "solve_config=tiny via extract_roots_v0.py",
"ip_weights_uniform": true,
"bb_chips_derived": true,
"bb_chips": 80.86
}
}Field-by-field semantics: NodeDocument v1.
GET /v1/families/:fam/boards/:flop/node
The contract slot for non-root nodes. Tier root has no tree data, so this
returns a typed 501 — deliberately, with the future already spelled out.
Tiers tree and live will serve identical NodeDocument v1 responses from
this exact URL.
{
"error": {
"code": "TIER_NOT_AVAILABLE",
"message": "Family \"100bb_3bet_call_p7v5_n13380\" is served at tier \"root\", which only carries root-node documents. Non-root nodes arrive with tier \"tree\" (full-tree boardpacks) and tier \"live\" (real-time solves) and will be served from this exact endpoint as NodeDocument v1. The root document is available now at /v1/families/100bb_3bet_call_p7v5_n13380/boards/Ks7s6s.",
"details": {
"tier": "root",
"requested_path": "root.bet_55",
"available_paths": ["root"],
"planned_tiers": ["tree", "live"]
}
}
}This 501 is what the strategy browser's locked tree slots map to.