This page documents two core endpoints for probabilistic action modeling and Bayesian range updates. All examples use a black theme and reference local development at https://www.holdemapi.com.
Hold’em API’s decision models are trained on millions of real, anonymized hand histories from online cash games and tournaments. We combine population behavior with solver-guided augmentation to learn action probabilities, range transitions, and equity patterns that reflect how people actually play—across positions, stack depths, and streets.
Histories are aggregated, de-duplicated, and stripped of personal identifiers; we retain only event sequences (positions, actions, sizes, stacks, board/hand cards). Data is used in aggregate to train models—never to target individual players.
2–9 handed, preflop → river, common bet-sizing ladders, and typical formations (single-raised, 3-bet, multi-way where available).
Three heads: (1) fold/continue, (2) call vs. raise (conditional on continuing), and (3) aggressive size mix when betting/raising is selected.
Models are calibrated on held-out pools and checked with reliability curves. We ship versioned model IDsin responses where applicable.
Intended use: off-table analysis, training, and analytics—not real-time assistance during live play.
| Field | Type | Req? | Description |
|---|---|---|---|
| Format | string | Yes | Two-card combo like 'KdAs' or suited 'KhQh'. Use ranks [2–9,T,J,Q,K,A] and suits [c,d,h,s]. |
| Case | string | No | Uppercase recommended for clarity (e.g., As, Kd). |
| Uniqueness | boolean | No | No duplicates in a single range payload. |
| Validity | string | No | Cards must be distinct; suit-sensitive for suited/offsuit combos. |
| Field | Type | Req? | Description |
|---|---|---|---|
| street | "preflop" | "flop" | "turn" | "river" | Yes | Determines required card count. |
| cards | string[] | Yes | Flop: 3, Turn: 4, River: 5. Preflop: []. |
| potBB | number | Yes | Current pot expressed in big blinds at decision time. |
| Field | Type | Req? | Description |
|---|---|---|---|
| actor | string | Yes | Seat label like UTG/HJ/CO/BTN/SB/BB. |
| type | "fold"|"check"|"call"|"bet"|"raise" | Yes | Action kind. |
| sizeBB | number | No | Required for bet/raise; total size in BB, not increment. |
| street | "preflop"|"flop"|"turn"|"river" | Yes | Street on which action occurred. |
Returns model fold/call/raise outputs, continuation probabilities, and (if facing a bet) a distribution over raise/bet size buckets. Includes per-model diagnostics and a sampled action with RNG metadata.
curl -X POST \
'https://www.holdemapi.com/api/p_actions' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer $API_KEY' \
-d '{
"hand": "KdAs",
"range": "TT+,AQs+",
"tau": 0.1,
"action": {
"type": "raise",
"actor": "CO"
},
"context": {
"board": {
"street": "turn",
"cards": [
"8h",
"5d",
"2s",
"Qd"
],
"potBB": 14.5
},
"history": [
{
"actor": "HJ",
"type": "raise",
"sizeBB": 2.5,
"street": "preflop"
},
{
"actor": "CO",
"type": "call",
"sizeBB": 2.5,
"street": "preflop"
},
{
"actor": "HJ",
"type": "bet",
"sizeBB": 5,
"street": "flop"
},
{
"actor": "CO",
"type": "call",
"sizeBB": 5,
"street": "flop"
},
{
"actor": "HJ",
"type": "bet",
"sizeBB": 10.5,
"street": "turn"
}
],
"effectiveStackBB": 80,
"numPlayers": 6,
"subjectPosition": "CO"
},
"options": {
"smoothingEps": 0.000001,
"aggressiveTemp": 1.2,
"returnDiagnostics": true
}
}'{
"ok": true,
"hand": "KdAs",
"equity": 0.54,
"rank": 72,
"length_range": 34,
"board": { "cards": ["8h", "5d", "2s", "Qd"], "potBB": 14.5 },
"facingBet": true,
"output": { "fold": 0.49, "call": 0.2927041660265801, "raise": 0.2172958339734199 },
"givenContinue": { "call": 0.5739297373070198, "raise": 0.4260702626929802, "sum": 1 },
"sizes": ["22%","34%","47%","63%","85%","112%","147%","200%","shove"],
"weights": [0.02,0.04,0.08,0.15,0.26,0.25,0.12,0.06,0.02],
"debug": {
"models": {
"FC": 0.48897695541381836,
"CR": 0.4260702626929802,
"RS": [0.02,0.04,0.08,0.15,0.26,0.25,0.12,0.06,0.02]
}
},
"selected": {
"action": "raise",
"amountBB": 16.24,
"bucket": "112%",
"rng": { "fc": 0.13, "cr": 0.42, "rs": 0.37 }
}
}// ----- Request
export interface PAction {
type: 'fold' | 'check' | 'call' | 'bet' | 'raise';
actor: string; // e.g., 'CO', 'HJ', 'SB'
sizeBB?: number; // optional when type is bet/raise
street?: 'preflop' | 'flop' | 'turn' | 'river';
}
export interface HistoryEvent extends PAction {
// Required: each event should include street to anchor order
street: 'preflop' | 'flop' | 'turn' | 'river';
}
export interface BoardContext {
street: 'preflop' | 'flop' | 'turn' | 'river';
cards: string[]; // e.g., ['8h','5d','2s','Qd'] (empty on preflop)
potBB: number; // pot size in big blinds at this decision
}
export interface DecisionContext {
board: BoardContext;
history: HistoryEvent[];
effectiveStackBB: number;
numPlayers: number;
subjectPosition: string; // hero seat label, e.g. 'CO'
}
export interface PActionOptions {
smoothingEps?: number; // probability floor; avoids zeros
aggressiveTemp?: number; // temperature for raise/bet softness
returnDiagnostics?: boolean;
}
export interface PActionRequest {
hand: string; // 'KdAs'
range?: WeightedRange; // opponent prior (defaults to uniform)
tau?: number; // temperature for fold gate
action: PAction; // current contemplated action (used for conditioning/labels)
context: DecisionContext; // full state
options?: PActionOptions;
}
// ----- Response
export interface PActionResponse {
ok: boolean;
facingBet: boolean;
hand: string;
rank: number;
length_range: number; // combos in hero range after blockers (max 1326)
board: { cards: string[]; potBB: number };
output: { fold: number; call: number; raise: number } | { check: number; bet: number };
givenContinue: { call: number; raise: number; sum: 1 };
sizes: string[];
weights: number[];
debug?: { models: { FC: number; CR: number; RS: number[] } };
selected: {
action: 'fold' | 'check' | 'call' | 'raise';
amountBB: number | null;
bucket: string | null;
rng: { fc: number; cr: number; rs: number };
};
}Performs a Bayesian-style update of an opponent’s weighted range after observing an action at the current node. Supports temperature/likelihood shaping, target-KL constraints, and an optional equity gate.
curl -X POST \
'https://www.holdemapi.com/api/update_range' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer $API_KEY' \
-d '{
"range": {
"AsKd": 0.3,
"AsKs": 0.22,
"KhQh": 0.18,
"7c7d": 0.15,
"JcTc": 0.15
},
"action": {
"type": "raise",
"sizeBB": 95,
"actor": "SB"
},
"context": {
"board": {
"street": "preflop",
"cards": [],
"potBB": 12.5
},
"history": [
{
"actor": "UTG",
"type": "fold",
"street": "preflop"
},
{
"actor": "HJ",
"type": "raise",
"sizeBB": 2.5,
"street": "preflop"
},
{
"actor": "CO",
"type": "raise",
"sizeBB": 8.5,
"street": "preflop"
},
{
"actor": "SB",
"type": "raise",
"sizeBB": 95,
"street": "preflop"
}
],
"effectiveStackBB": 95,
"numPlayers": 6,
"subjectPosition": "SB"
},
"options": {
"aggressiveTemp": 1.2
}
}'{
"priorRange": {
"KdAs": 0.35,
"KsAs": 0.25,
"QhKh": 0.15,
"7c7d": 0.15,
"TcJc": 0.1
},
"priorRangeCount": 5,
"updatedRange": {
"KdAs": 0.622111252028909,
"7c7d": 0.377888747971091
},
"updatedRangeCount": 2,
"fcModel": {
"continue": 0.2714932126696833,
"fold": 0.7285067873303167
},
"fcModelRaw": {
"continue": 0.48897695541381836,
"fold": 0.5110230445861816
},
"fcProbabilities": {
"KdAs": 0.41,
"KsAs": 0.38,
"QhKh": 0.29,
"7c7d": 0.12,
"TcJc": 0.08
},
"crProbabilities": {
"KdAs": 0.23,
"KsAs": 0.22,
"QhKh": 0.14,
"7c7d": 0.05,
"TcJc": 0.03
},
"modelInput": [
0.12,
0.34,
0.56
]
}// ----- Request
export type Combo = string; // e.g., 'KdAs', '7c7d'
export interface WeightedRange {
[combo: Combo]: number; // probabilities should sum ≈ 1 (lib can renormalize)
}
export interface UpdateRangeOptions {
aggressiveTemp?: number; // soften raise/bet logits
}
export interface UpdateRangeRequest {
range?: WeightedRange; // opponent prior (defaults to uniform)
action: {
type: 'fold' | 'check' | 'call' | 'bet' | 'raise';
sizeBB?: number;
actor: string; // seat label
};
context: {
board: { street: 'preflop' | 'flop' | 'turn' | 'river'; cards: string[]; potBB: number; };
history: { actor: string; type: 'fold'|'check'|'call'|'bet'|'raise'; sizeBB?: number; street: 'preflop'|'flop'|'turn'|'river'; }[];
effectiveStackBB: number;
numPlayers: number;
subjectPosition: string;
};
options?: UpdateRangeOptions;
}
// ----- Response
export interface UpdateRangeResponse {
priorRange: WeightedRange; // prior after pruning / normalization
priorRangeCount: number; // remaining combos in prior
updatedRange: WeightedRange; // posterior (default key)
updatedRangeCount: number; // combos with non-zero weight in posterior
fcModel?: { continue: number; fold: number }; // ratio of continuing combos
fcModelRaw?: { continue: number; fold: number }; // unadjusted model output
fcProbabilities?: WeightedRange; // FC fold probability per combo
crProbabilities?: WeightedRange; // CR aggressive probability per combo
actionProbabilities?: WeightedRange; // likelihood for observed action per combo
modelInput?: number[]; // shared CR/action model input (first combo)
}| HTTP | Code | When |
|---|---|---|
| 400 | BAD_REQUEST | Malformed cards/combos; missing street; bet/raise without sizeBB; invalid probabilities. |
| 401 | UNAUTHORIZED | Missing/invalid Authorization header. |
| 403 | FORBIDDEN | Plan limit exceeded or key lacks scope. |
| 409 | CONFLICT | History inconsistent with board/stacks; impossible sequence detected. |
| 422 | UNPROCESSABLE_ENTITY | Range doesn’t sum (and cannot be renormalized); negative/NaN weights. |
| 429 | RATE_LIMITED | Too many requests. |
| 500 | INTERNAL_ERROR | Unexpected server error. |