GTOkiller
  • Home
  • Solver
  • MDA
  • Pricing
  • Invite a Friend
  • Blog
On this site
GTOKiller API
v1
Getting started
  • Quickstart
  • Authentication
Core concepts
  • Inputs
  • node id
  • Outputs
  • Discovery mode
  • Stateless mode
Reference
  • GET /v1/strategy
  • GET /v1/health
  • Errors
Need a key?

Request a trial key on Discord.

GTOKiller API
v1
Getting started
  • Quickstart
  • Authentication
Core concepts
  • Inputs
  • node id
  • Outputs
  • Discovery mode
  • Stateless mode
Reference
  • GET /v1/strategy
  • GET /v1/health
  • Errors
Need a key?

Request a trial key on Discord.

  1. Docs
  2. Reference
  3. GET /v1/strategy

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.

ParameterTypeDescription
platformRequired
stringPool / 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
stringPool 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
stringPosition dyad <aggressor>_<caller> (e.g. btn_bb). Lowercase letters/digits/_, max 40 chars. See the note below — this is NOT <ip>_<oop>.
flopRequired
string3 cards as 6 chars, e.g. 2c2d2h. Any suit order; ranks and suits are case-insensitive (same for turn, river and hand).
turn
stringOptional turn card (2 chars). Empty string treated as absent.
river
stringOptional river card (2 chars). Requires turn: river without turn answers 422 validation_error. Empty string treated as absent.
nodeRequired
stringRequired on every request. Max 200 chars.
hand
string4 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

HeaderValueDescription
X-API-KeyRequired
sk_live_…Strict format: ^sk_live_[A-Za-z0-9]{32}$.
X-Request-ID
8–128 charsOptional 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

HeaderValueDescription
X-Request-ID
req_…Echoed or generated. Use it when contacting support.
X-Cache
HIT | MISSHIT 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
intCurrent tier RPS.
X-RateLimit-Remaining
intInformational, 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
intSoft monthly quota.
X-RateLimit-Monthly-Remaining
intCalls left under the soft quota. Can go NEGATIVE while in overage (still served, billed extra).
X-RateLimit-HardCap
intAbsolute monthly ceiling. At or above it, requests answer 429 until the month rolls over.
Retry-After
intOn 429 only: seconds to wait before retrying (currently always 1).
Server-Timing
metricsPer-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.

See the Errors page →

Previous
Stateless mode
Next
GET /v1/health