On this site
GET /v1/strategy
Returns the optimal action mix for a single decision.
GET/v1/strategyX-API-Key
Query parameters
All parameters are URL query string. There is no request body.
| Parameter | Type | Description |
|---|---|---|
platformRequired | string | Pool / site identifier (e.g. gg). Lowercase letters/digits/_, max 30 chars. Which platforms have data depends on your account's strategy folder — see Inputs for live values. |
stakesRequired | string | <sb>_<bb> integers (e.g. 10_50). Must be in your account's stake allowlist or the request answers 403 stake_not_allowed. |
playerTypeRequired | string | Pool segment (e.g. regs). Lowercase letters/digits/_, max 30 chars. |
situationRequired | "srp" | "3bet" | Preflop scenario: srp (single-raised pot) or 3bet. Lowercase letters/digits/_, max 30 chars. |
positionRequired | string | Position dyad <aggressor>_<caller> (e.g. btn_bb). Lowercase letters/digits/_, max 40 chars. See the note below — this is NOT <ip>_<oop>. |
flopRequired | string | 3 cards as 6 chars, e.g. 2c2d2h. Any suit order; ranks and suits are case-insensitive (same for turn, river and hand). |
turn | string | Optional turn card (2 chars). Empty string treated as absent. |
river | string | Optional river card (2 chars). Requires turn: river without turn answers 422 validation_error. Empty string treated as absent. |
nodeRequired | string | Required on every request. Max 200 chars. |
hand | string | 4 chars, e.g. AsKh. Two identical cards rejected. Required on every request except discovery=true, where it is ignored if sent. |
verbosity | "brief" | "full" | brief (default) or full. Brief carries the reduced context (round_start_pot_bb, to_act); full expands it (street, hand, board, stacks_bb, spr, positions) and adds raise_ratio on raises. pot_pct and node_token are in both. Ignored when discovery=true. |
discovery | "true" | "false" | "true" switches the endpoint to discovery mode: structure only, hand ignored, free of charge. See Discovery mode. |
audit | "true" | "false" | "true" adds the audit block to the response: spot, node, coverage and tree revision of this decision, for grouping your logs. Nothing else in the response changes. See Outputs. |
position is aggressor_caller, not ip_oop
position names the preflop aggressor first and the caller second: in sb_bb the SB opens and is OOP postflop, so it is not an ip/oop pair. Code the aggressor/caller rule and gate every decision on the to_act field of the response, never on the position string.
Strict validation
Validation is strict: any query parameter not listed here answers 422 validation_error (unrecognized_keys). Strip tracking params and typos before calling.
Request headers
| Header | Value | Description |
|---|---|---|
X-API-KeyRequired | sk_live_… | Strict format: ^sk_live_[A-Za-z0-9]{32}$. |
X-Request-ID | 8–128 chars | Optional ID for tracing. Echoed in response headers and logs. |
Response
Both verbosities share the envelope: data (context + actions), node_id and source at the top level. Field-by-field docs live on the Outputs page.
200Brief mode · 200
{
"data": {
"context": {
"round_start_pot_bb": 5.5,
"to_act": "ip"
},
"actions": [
{ "type": "check", "node_token": "x", "frequency": 0 },
{ "type": "bet", "node_token": "b1.82", "frequency": 0.01, "amount": 1.82, "pot_pct": 0.33 },
{ "type": "bet", "node_token": "b2.75", "frequency": 0.99, "amount": 2.75, "pot_pct": 0.5 }
]
},
"node_id": "root-x",
"source": "custom"
}- source — which strategy tree served the response: custom (your account's dedicated folder, the normal case) or v1 (shared default tree). Present in both verbosities; not present on discovery responses.
- audit: only with audit=true. Aggregation key of the decision (spot_id, node_path, coverage, strategy_revision…), at the top level next to node_id. On 404 not_found and 422 combo_not_in_range it sits inside error instead.
Response headers
| Header | Value | Description |
|---|---|---|
X-Request-ID | req_… | Echoed or generated. Use it when contacting support. |
X-Cache | HIT | MISS | HIT when the strategy node came from the in-memory cache. The CDN in front appends its own entry, so on the wire the header reads e.g. "HIT, MISS" — the FIRST value is the API's; the CDN's is always MISS because API responses are no-store. |
X-RateLimit-Limit | int | Current tier RPS. |
X-RateLimit-Remaining | int | Informational, not a live gauge: the implementation emits the constant rps − 1 on every allowed request and 0 on a 429. Pace your client yourself and back off on 429 + Retry-After. |
X-RateLimit-Monthly-Limit | int | Soft monthly quota. |
X-RateLimit-Monthly-Remaining | int | Calls left under the soft quota. Can go NEGATIVE while in overage (still served, billed extra). |
X-RateLimit-HardCap | int | Absolute monthly ceiling. At or above it, requests answer 429 until the month rolls over. |
Retry-After | int | On 429 only: seconds to wait before retrying (currently always 1). |
Server-Timing | metrics | Per-pipeline-stage latency (security, pre_auth_rate_limit, auth, validation, stake_check, rate_limit, node_id_translate, fetch_storage, transform, total; plus diagnose_not_found on 404s and audit_meta with audit=true). Sent on 200 responses only. |
Errors
Every error code, its HTTP status and the 404 reason taxonomy live on the Errors page. The most common for /v1/strategy: 404 not_found (node id does not exist — the body says why), 422 combo_not_in_range (node exists, your hand does not reach it) and 422 validation_error.