Consulta prerresuelta
RÁPIDOSoluciones de preflop y más de 5.8M soluciones de flop. Devuelve una estrategia en milisegundos sin sondeo de tareas.
Empieza con preflopUsa MelaSolver GPU mediante una API de autoservicio. Empieza con una consulta pre-resuelta en milisegundos o envía una situación personalizada de flop, turn o river al grupo de resolución en tiempo real.
Descarga la colección pública, impórtala en Postman y establece la variable apiKey de la colección con tu clave de API antes de enviar una solicitud. Utiliza Authorization: Bearer {{apiKey}} y la URL base pública https://pokerai.bet; los ejemplos incluidos abarcan la estrategia preflop GTO y la textura del board de PokerKit.
Colección de Postman El archivo descargable no contiene ninguna clave real, Cookie ni endpoint privado. Para consultar el contrato público completo, consulta la Referencia de la API y la instantánea de OpenAPI.
Ambas usan la misma clave de API y cuota mensual.
Soluciones de preflop y más de 5.8M soluciones de flop. Devuelve una estrategia en milisegundos sin sondeo de tareas.
Empieza con preflopÁrboles personalizados de flop, turn y river. Envía una vez, consulta periódicamente por ID de tarea y luego recupera la estrategia resuelta.
Enviar una tarea de resoluciónInstala, autentícate y llama. No hay nada más que aprovisionar.
curl -s https://pokerai.bet/v1/gto/preflop \
-H "Authorization: Bearer $POKERAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"hole_cards":"AhKh","positions":{"hero":"UTG"},"preflop_actions":[{"position":"SB","action":"small blind","amount":0.5},{"position":"BB","action":"big blind","amount":1}]}'
{
"hole_cards": "AhKh",
"situation": "RFI",
"strategy": [
{ "action": "raise", "frequency": 1, "amount_bb": 3, "sizing_pot": 0.8 }
],
"quota": { "used": 6, "limit": 100 }
}
Pasa de la primera llamada a producción sin tener que buscar en una única página larga.
Cada solicitud debe incluir una clave API. Obtén una clave en 60 segundos:
export POKERAI_API_KEY=gto_xxxxxxxx, y podrás ejecutar el Inicio rápido de abajo.A partir de entonces, envía la misma clave (el gto_xxx que acabas de copiar — este es el «token Bearer») en un encabezado de solicitud en cada solicitud. Elige cualquiera de las formas siguientes: es una clave, no dos:
Authorization: Bearer gto_xxxxxxxx # estándar (recomendado; coincide con el esquema OpenAPI BearerApiKey)
# o (totalmente equivalente; elige una)
X-API-Key: gto_xxxxxxxx # equivalente (esquema OpenAPI XApiKey); útil para algunas pasarelas / SDK / pruebas rápidas
Dos tipos de cuota mensual, medidos por separado y restablecidos el día 1 de cada mes; el uso actual está en la consola:
/v1/gto/range, y llamadas de rango proyectado consumen 1 cada una./v1/gto/solver consume 1 cada vez que inicia una nueva resolución; reutilizar una resolución en caché y obtener el árbol/nodo es gratuito (la respuesta incluye el solve_quota cuando se cobra y no lo incluye cuando no se cobra).Todos los errores devuelven un JSON uniforme: { "error": "<code>", "message": "<description>" }. Algunas variantes: algunos 502 usan reason en lugar de message; el 429 cuando todos los solvers están ocupados tiene el aspecto { "status": "busy", "message": ... }. Los valores de error específicos de cada endpoint se encuentran en la tabla «Posibles errores» de cada endpoint; los códigos de estado comunes aparecen a continuación:
| HTTP | error / significado | ¿reintentar? |
|---|---|---|
| 400 | Entrada no válida o campo ausente (consulta la tabla de cada endpoint para el error específico). | No, corrige la entrada |
| 401 | missing_api_key / invalid_api_key: clave ausente o no válida. | No, comprueba la clave |
| 403 | invalid_node_token / invalid_solve: token/identificador no válido o no te pertenece. | No, vuelve a obtener el árbol / reprograma primero |
| 404 | no_solution: todavía no hay datos GTO para esta situación. | No, cambia la situación |
| 429 | quota_exceeded (general) / solve_quota_exceeded (solve): cuota mensual agotada. | No, se restablece el día 1 o mejora tu cuota |
| 429 | status: busy: todos los solvers están ocupados (solo /v1/gto/solver), sin cargo. | Sí, espera y vuelve a intentarlo |
| 502 | no_result (reason: timeout / no_worker_available) / auth_unavailable / solver_unreachable: backend temporalmente no disponible. | Sí, espera y vuelve a intentarlo 2–3 veces |
400 (entrada no válida):
{
"error": "invalid_board",
"message": "board must be 3 cards, e.g. \"2c2h2s\""
}
401 (clave ausente) / 404 (sin datos) / 429 (cuota agotada) — campo único o mensaje breve:
{ "error": "missing_api_key" }
{ "error": "no_solution", "message": "no GTO data for this spot/board" }
{ "error": "quota_exceeded" }
502 (backend temporalmente no disponible, se puede reintentar):
{
"error": "no_result",
"reason": "timeout"
}
Reintento: solo vale la pena reintentar 429 busy y 502 — usa retroceso exponencial (empieza en ~1 s, duplica, como máximo 2–3 veces). El resto (400/401/403/404/cuota agotada) son definitivos y reintentarlos es inútil: corrige la entrada / cambia la clave / vuelve a obtener el árbol, o espera a que la cuota se restablezca el día 1 del mes. No hay límite de velocidad por segundo, por lo que no existe la cabecera Retry-After.
Cuando tengas una clave (consulta arriba), guárdala como POKERAI_API_KEY y copia este curl — la llamada correcta más sencilla: Hero tiene una oportunidad de apertura en UTG (RFI) y la solución preresuelta preflop se devuelve en milisegundos. También puedes copiar el mismo fragmento inicial desde el panel.
curl -s https://pokerai.bet/v1/gto/preflop \
-H "Authorization: Bearer $POKERAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"hole_cards":"AhKh","positions":{"hero":"UTG"},"preflop_actions":[{"position":"SB","action":"small blind","amount":0.5},{"position":"BB","action":"big blind","amount":1}]}'
Respuesta real (UTG con AKs, oportunidad de apertura → abre el 100 % a 3BB):
{
"hole_cards": "AhKh",
"situation": "RFI",
"strategy": [
{ "action": "raise", "frequency": 1, "amount_bb": 3, "sizing_pot": 0.8 }
],
"quota": { "used": 6, "limit": 100 }
}
¿Enfrentas una subida? Solo añade la acción del oponente a preflop_actions (agrega {"position":"UTG","action":"raise","amount":3} y cambia Hero a MP → se convierte en una situación de 3bet y situation devuelve Raise). Se devuelve la frecuencia mixta de cada acción (sin acción recomendada; elige tú según frequency). Las secciones siguientes se organizan en tres partes: Soluciones preresueltas (preflop / flop), cálculo del solver en tiempo real y conversión de rangos.
¿No quieres escribir HTTP a mano? Los clientes oficiales se generan automáticamente a partir de la especificación OpenAPI y están totalmente tipados, por lo que siempre siguen la API. La autenticación solo requiere tu clave API.
pip install pokerai-bet # nombre de distribución pokerai-bet, importar como pokerai
La misma situación del Inicio rápido (apertura Hero UTG), tipada:
from pokerai import AuthenticatedClient
from pokerai.api.lookup import preflop_strategy
from pokerai.models import (
PreflopRequest, PreflopRequestPositions, PreflopRequestPreflopActionsItem,
)
from pokerai.models.preflop_request_preflop_actions_item_action import (
PreflopRequestPreflopActionsItemAction as Act,
)
from pokerai.models.position import Position
client = AuthenticatedClient(base_url="https://pokerai.bet", token="gto_...")
resp = preflop_strategy.sync(client=client, body=PreflopRequest(
hole_cards="AhKh",
positions=PreflopRequestPositions(hero=Position.UTG),
preflop_actions=[
PreflopRequestPreflopActionsItem(position=Position.SB, action=Act.SMALL_BLIND, amount=0.5),
PreflopRequestPreflopActionsItem(position=Position.BB, action=Act.BIG_BLIND, amount=1.0),
],
))
print(resp.to_dict())
Resultado real (la misma situación que el Inicio rápido):
{"hole_cards": "AhKh", "situation": "RFI",
"strategy": [{"action": "raise", "frequency": 1, "sizing_pot": 0.8, "amount_bb": 3}],
"quota": {"used": 2702, "limit": 100000}}
npm install @pokerai/client
import { createPokeraiClient } from "@pokerai/client";
const client = createPokeraiClient({ apiKey: "gto_..." });
const { data, error } = await client.POST("/v1/gto/preflop", {
body: {
hole_cards: "AhKh",
positions: { hero: "UTG" },
preflop_actions: [
{ position: "SB", action: "small blind", amount: 0.5 },
{ position: "BB", action: "big blind", amount: 1 },
],
},
});
if (error) throw new Error(JSON.stringify(error));
console.log(data.situation, data.strategy);
// "RFI" [{ action: "raise", frequency: 1, amount_bb: 3, sizing_pot: 0.8 }]
Las rutas, los cuerpos de solicitud y los campos de respuesta se comprueban por tipo — tu editor completa automáticamente toda la API. Los tipos se generan desde la especificación mediante openapi-typescript; el tiempo de ejecución es openapi-fetch.
Permite que Claude / Cursor y compañía llamen a la API de Pokerai como herramientas (@pokerai/mcp):
// mcp.json
{ "mcpServers": { "pokerai": {
"command": "npx", "args": ["-y", "@pokerai/mcp"],
"env": { "POKERAI_API_KEY": "gto_..." }
}}}
5 herramientas de búsqueda preresuelta de forma predeterminada; añade "POKERAI_ENABLE_SOLVE": "1" para habilitar las herramientas del solver en tiempo real (consume cuota de resolución).
El modelo mental general — léelo una vez y las secciones por endpoint de abajo resultarán más sencillas.
Cada estrategia devuelve la frecuencia mixta de cada acción (0–1) y no elige la acción por ti — la implementas tú a partir de frequency (toma la probabilidad máxima o muestrea aleatoriamente por frecuencia).
Cada bet/raise contiene dos campos de tamaño: amount_bb (la cantidad absoluta, es decir, los BB a los que subes hasta) y sizing_pot (el valor relativo al bote, la convención estándar de % del bote):
Ejemplo: 3bet a 9 ante una apertura de 3 — el bote es 4,5; tras el call, 4,5+3=7,5; la subida excede en 9−3=6, por lo que sizing_pot = 6/7,5 = 0,8. Cuando es all-in también incluye allin: true.
Tanto el árbol de decisión del flop como el solver en tiempo real constan de dos pasos: primero obtén todo el árbol (cada nodo de decisión contiene un token) y luego usa el token del nodo Hero para obtener la estrategia de ese paso.
obtener árbol /flop/tree o /solver (+ sondear /solver/tree)
└─→ nodes[]: cada nodo contiene is_hero + token
└─→ elegir el nodo con is_hero:true
obtener nodo /flop/node o /solver/node (el cuerpo contiene el token de ese nodo)
└─→ la estrategia mixta de este paso
/flop/tree (cobra 1) → /flop/node (gratis). El nodo root = la primera decisión de Hero./solver devuelve un identificador solve (cobra 1) → sondeo de /solver/tree + /solver/node (ambos gratis). El rango se proporciona solo una vez, durante la programación, y no se vuelve a pasar.Notación de la ruta de nodo (dos convenciones, según la fuente del árbol): el árbol de decisión del flop usa BET_8 (guion bajo, BB entero); el árbol del solver usa BET 8.000000 (espacio, 6 decimales). Al pasar node_id / navegar, debe coincidir con las etiquetas de ese árbol (o en solver_results) carácter por carácter.
Después de programar, consulta periódicamente el spot_status de /solver/tree: available (no programado) → computing (resolviendo; sigue consultando) → queryable (se pueden obtener nodos) → expired (la caché fue liberada por TTL; debe volver a programarse). Al terminar las consultas, puedes opcionalmente llamar a /solver/release para devolver el puerto al grupo de puertos de inmediato (de lo contrario, TTL lo libera); después de liberarlo, consultas posteriores sobre este identificador de solve devuelven expired.
preflop y flop usan soluciones GTO preresueltas, servidas al instante, adecuadas para casos de uso que requieren una respuesta rápida. El stack efectivo se fija en 100BB (preresuelto, no es una entrada). Para calcular el flop en vivo con el solver real, consulta la siguiente sección.
POST https://pokerai.bet/v1/gto/preflop consume 1 general
Esquema completo de parámetros y respuesta, y pruébalo en directo → referencia interactiva.
No necesitas juzgar «cuántas apuestas hay en el bote»; proporciona en orden las acciones preflop anteriores de Hero y el servidor deriva automáticamente el spot (sin abrir / ante una subida / 3bet / 4bet…).
| campo | tipo | descripción |
|---|---|---|
hole_cards | string | Las 2 cartas privadas de Hero; por ejemplo, "AdKd". |
positions.hero | string | La posición de Hero, una de SB BB UTG MP CO BTN (situada dentro de positions). |
preflop_actions | array | La secuencia de acciones completa y explícita desde la ciega pequeña hasta el jugador inmediatamente anterior a Hero (Hero no está en la secuencia; la posición de Hero se indica mediante positions.hero y la secuencia termina en el jugador anterior a Hero). Cada elemento es { position, action, amount, allin? }; consulta la tabla siguiente. |
preflop_version | string | Opcional. Qué conjunto de tablas preflop 6max usar: 6max (predeterminado) / 6max_RC_100bb_200NL / 6max_RC_100bb_100NL / 6max_RC_40bb. Omítelo para el predeterminado de la plataforma (6max); un valor desconocido -> 400 unsupported_preflop_version. Distintas versiones proporcionan distintas frecuencias para el mismo spot. |
| campo | tipo | descripción |
|---|---|---|
position | string | La posición de esta acción, una de SB BB UTG MP CO BTN. |
action | string | ∈ "small blind" / "big blind" / "raise" / "call" / "fold" (ten en cuenta que las ciegas son cadenas de dos palabras). |
amount | number | El importe incremental recién invertido por esta acción (BB, no el total acumulado). Ejemplos: ciega pequeña 0.5; ciega grande 1; una subida inicial a 3 → amount 3 (desde 0); un jugador que ya invirtió 1 y vuelve a subir a 9 → amount 8. fold lo omite (cuenta como 0). Bote = suma de todos los amount. |
allin | boolean | Opcional. Marca un all-in de stack corto (importe de apuesta/igualada inferior a la subida mínima); cuando es true, se omite la comprobación de subida mínima. |
Validación (infracción → 400 invalid_actions): la secuencia debe comenzar con small blind (0.5) y luego big blind (1); cada raise/call necesita un amount positivo; un raise debe tener un total acumulado que supere la apuesta actual y cumpla la subida mínima (= apuesta actual + el tamaño de la subida anterior; por tanto, apertura ≥ 2BB y una 3bet sobre una apertura a 3 debe ser ≥ 5BB), salvo allin:true; el total acumulado de un call debe ser exactamente igual a la apuesta actual, salvo allin:true.
Los importes exactos solo afectan al bote / sizing_pot, no a las frecuencias: proporcionar valores exactos de amount solo hace exactos el bote / sizing_pot; las frecuencias GTO se determinan por el spot (RFI / 3bet / 4bet + posición) y no cambian con el tamaño de la apuesta.
curl -s https://pokerai.bet/v1/gto/preflop \
-H "Authorization: Bearer $POKERAI_API_KEY" -H "Content-Type: application/json" \
-d '{"hole_cards":"AhKh","positions":{"hero":"MP"},"preflop_version":"6max_RC_100bb_200NL",
"preflop_actions":[{"position":"SB","action":"small blind","amount":0.5},
{"position":"BB","action":"big blind","amount":1},
{"position":"UTG","action":"raise","amount":3}]}'
Omite preflop_version para el valor predeterminado (6max). Las versiones disponibles se enumeran a continuación, o consúltalas en directo con GET /v1/gto/preflop/versions.
{"hole_cards": "AhKh", "situation": "Raise", "strategy": [{"action": "raise", "frequency": 1, "amount_bb": 9, "sizing_pot": 0.8}], "quota": {"used": 7, "limit": 100}}
| campo | descripción |
|---|---|
hole_cards | La mano repetida en la respuesta. |
situation | El estado al que se enfrenta la mesa cuando le toca a Hero: RFI (nadie en el bote, Hero tiene oportunidad de abrir) / Limp (alguien hizo limp, sin subida) / Raise (ante una sola subida inicial) / 3-Bet / 4-Bet / 5-Bet. Nota: BB siempre llega a Limp (alguien debe haber entrado en el bote antes de que actúe). |
strategy[] | La estrategia mixta de cada acción. raise incluye amount_bb (el importe absoluto elevado a, en BB) y sizing_pot (consulta tamaño de apuesta). El amount_bb preflop se establece según el número de subidas antes de Hero; consulta la tabla siguiente. No se devuelve ninguna acción recomendada; elige tú según frequency. |
quota | Uso de la cuota general de este mes (used / limit). |
Preflop amount_bb (derivado del bote de flop preresuelto, subida a):
| número de subidas antes de Hero | situación | amount_bb |
|---|---|---|
| 0 | apertura | 3 |
| 1 | 3bet | 9 |
| 2 | 4bet | 25 |
| ≥3 | 5bet+ | all-in 100 (allin: true) |
preflop_versionEl mismo 6max, distintos conjuntos de tablas preflop (las frecuencias difieren para el mismo spot); omítelo para el valor predeterminado 6max. La lista autoritativa es el endpoint de descubrimiento GET /v1/gto/preflop/versions (gratuito; devuelve id + label + default):
id (pasar como preflop_version) | descripción |
|---|---|
6max (predeterminado) | 6 max 100bb Deepsolver |
6max_RC_100bb_200NL | 6 max 100bb GG 200NL 3b/f 2.2x - 2.5x |
6max_RC_100bb_100NL | 6 max 100bb GG 100NL 3b/f |
6max_RC_40bb | 6 max 40bb GG 100NL |
curl -s https://pokerai.bet/v1/gto/preflop/versions -H "Authorization: Bearer $POKERAI_API_KEY"
// {"versions": [{"id": "6max", "label": "6 max 100bb Deepsolver", "default": true}, …], "default": "6max"}
| HTTP | error | desencadenante / cómo corregirlo |
|---|---|---|
| 400 | invalid_hole_cards | hole_cards no son 2 cartas (p. ej., "AdKd"). |
| 400 | unsupported_table_size / invalid_positions / invalid_actions | El tipo de mesa (actualmente solo 6max), hero/las posiciones o preflop_actions no son válidos. |
| 400 | unsupported_preflop_version | preflop_version no está en el conjunto permitido (6max / 6max_RC_100bb_200NL / 6max_RC_100bb_100NL / 6max_RC_40bb). |
| 404 | no_solution | No hay una solución prerresuelta para este spot preflop; cambia el spot. |
Descargar: request.jsonresponse.json
POST https://pokerai.bet/v1/gto/preflop/range · el rango completo de 13×13 para un spot (posición + línea de acciones), que devuelve fold/call/raise de los 169 tipos de mano en una llamada. Sin hole_cards (el spot proviene de positions + preflop_actions). Consume 1 cuota general (una llamada, no 169). Para representar una cuadrícula de rangos.
// Solicitud (sin hole_cards)
{"table_size": "6max", "positions": {"hero": "BTN"}, "preflop_actions": [{"position": "SB", "action": "small blind", "amount": 0.5}, {"position": "BB", "action": "big blind", "amount": 1}, {"position": "UTG", "action": "fold"}, {"position": "MP", "action": "fold"}, {"position": "CO", "action": "fold"}]}
// Respuesta
{ "range": {"22": {"fold": 0.69, "call": 0, "raise": 0.31}, "33": {"fold": 0, "call": 0, "raise": 1}, "ATs": {"fold": 0, "call": 0, "raise": 1}, "AKs": {"fold": 0, "call": 0, "raise": 1}, "AKo": {"fold": 0, "call": 0, "raise": 1}, "KQs": {"fold": 0, "call": 0, "raise": 1}, "72o": {"fold": 1, "call": 0, "raise": 0}, "JJ": {"fold": 0, "call": 0, "raise": 1} , …169 manos en total… },
"quota": {"used": 7, "limit": 100} }
Notación de manos: pareja AA, del mismo palo AKs, de distinto palo AKo (la carta alta primero); el fold+call+raise de cada entrada≈1. Esquema completo / pruébalo en directo → referencia interactiva.
La estrategia de flop es un árbol de decisiones: primero obtén el árbol (recibiendo todos los nodos de decisión + el token de cada nodo), tu sistema recorre la ruta del árbol según las apuestas reales y, en el nodo de Hero, obtiene la estrategia de ese paso. Dos pasos, igual que el solucionador (tree → node).
POST https://pokerai.bet/v1/gto/flop/tree · entrada board + pot_type + positions (no se necesitan hole_cards, el árbol es independiente de la mano).
Esquema completo de parámetros y respuesta, y pruébalo en directo → referencia interactiva.
board | Las 3 cartas del flop, p. ej., "2c2h2s". |
pot_type | "SRP" con una sola subida / "3BET" / "4BET" / "LIMP" limpeado. |
positions | La posición de cada rol (SB BB UTG MP CO BTN), necesaria por pot_type como se indica a continuación. |
flop_version | Opcional. Qué conjunto de datos de flop (uno resuelto por versión preflop): 6max (predeterminado) / 6max_RC_100bb_200NL / 6max_RC_100bb_100NL / 6max_RC_40bb. Omítelo para el valor predeterminado (6max); si esa versión no tiene datos para el spot, degrada con elegancia a 6max; un valor desconocido -> 400 unsupported_flop_version. Independiente de preflop_version. Los tokens de nodo llevan esta versión, por lo que /v1/gto/flop/node permanece en el mismo conjunto de datos. |
| pot_type | posiciones necesarias | valor de Hero |
|---|---|---|
SRP | hero, raiser, caller | subidor o pagador |
3BET / 4BET | hero, raiser, three_bettor | subidor o quien hace la tercera apuesta |
LIMP | hero, limper | uno de Hero o el limper debe ser BB |
// Solicitud (sin hole_cards)
{"board": "2c2h2s", "pot_type": "SRP", "positions": {"hero": "UTG", "raiser": "UTG", "caller": "BTN"}}
// Respuesta (36 nodos en total; se muestran los primeros 5)
{"board": ["2c", "2h", "2s"], "pot_type": "SRP", "pot": 7.5, "effective_stack": 97, "oop_range": "AA:1,AKs:1,AQs:1,AJs:1,ATs:1,A9s:1,A8s:1,A7s:1,A6s:1,A5s:1,…", "ip_range": "AQs:0.05,AJs:0.86,ATs:0.436,A9s:0.356,A8s:0.36,A7s:0.196,…", "node_count": 36, "nodes": [{"node": "root", "is_hero": true, "token": "eyJ…"}, {"node": "root/BET_4", "is_hero": false, "token": "eyJ…"}, {"node": "root/BET_8", "is_hero": false, "token": "eyJ…"}, {"node": "root/BET_97", "is_hero": false, "token": "eyJ…"}, {"node": "root/CHECK", "is_hero": false, "token": "eyJ…"}, …], "quota": {"used": 7, "limit": 100}}
| campo | descripción |
|---|---|
oop_range / ip_range | El rango inicial de este punto (cadena de combinaciones ponderadas), utilizado como pesos iniciales para la conversión de rangos. |
nodes[] | Todos los nodos de decisión: node (ruta de acciones, p. ej. "root/CHECK/BET_8"), is_hero (si es un punto de decisión de Hero), token (la credencial para obtener la estrategia de ese nodo, se pasa al paso 2; vinculada a la cuenta + spot, no se puede falsificar). |
pot / effective_stack / node_count | Pozo, stack efectivo (BB) y número total de nodos de decisión. |
quota | Uso de la cuota general de este mes (used / limit). |
POST https://pokerai.bet/v1/gto/flop/node · lleva node (el token de algún nodo del paso 1). Con hole_cards → la estrategia mixta para esa mano; sin hole_cards → la estrategia de rango completo.
Esquema completo de parámetros/respuesta y prueba en vivo → referencia interactiva.
Toda decisión de Hero pasa por aquí: la primera acción de Hero = el nodo root (OOP actúa primero, check/bet); cuando Hero está IP, enfrenta una apuesta o actúa por segunda vez, elige el nodo correspondiente con is_hero:true (p. ej., root/CHECK/BET_8 = hice check y ahora enfrento una apuesta → fold/call/raise). El árbol del flop es de una sola calle; para varias calles (turn/river) usa /v1/gto/solver/*.
// Solicitud (nodo de Hero, con hole_cards) -> estrategia de Hero
{"node": "eyJ…", "hole_cards": "AdKd"}
{"hole_cards": "AdKd", "node": "root", "is_hero": true, "strategy": [{"action": "check", "frequency": 0.7208}, {"action": "bet", "amount_bb": 4, "sizing_pot": 0.5333, "frequency": 0.0533}, {"action": "bet", "amount_bb": 8, "sizing_pot": 1.0667, "frequency": 0.2259}, {"action": "bet", "amount_bb": 97, "sizing_pot": 12.9333, "allin": true, "frequency": 0}]}
// Solicitud (sin hole_cards) -> estrategia de rango completo
{"node": "eyJ…"}
{"node": "root/BET_4", "is_hero": false, "actions": [{"action": "call"}, {"action": "raise", "amount_bb": 12, "sizing_pot": 0.5161}, {"action": "raise", "amount_bb": 20, "sizing_pot": 1.0323}, {"action": "raise", "amount_bb": 97, "sizing_pot": 6, "allin": true}, {"action": "fold"}], "range_strategy": {"3d3c": [0.93067, 4e-05, 0.06922, 1e-05, 7e-05], "3h3c": [0.92172, 6e-05, 0.07812, 1e-05, 0.0001], "3h3d": [0.94334, 4e-05, 0.05655, 1e-05, 7e-05], "…": "188 manos en total"}, "range_hand_count": 188}
| campo | descripción |
|---|---|
is_hero | Si este nodo es una decisión de Hero. |
strategy[] | Nodo de Hero (con hole_cards): la estrategia mixta para esta mano. action ∈ check / bet / call / raise / fold (bet = primera apuesta, raise = subida frente a una apuesta); bet/raise llevan amount_bb y sizing_pot (consulta tamaño de apuesta), y el all-in también lleva allin: true; frequency es una probabilidad de 0–1. No se devuelve ninguna acción recomendada; elige tú mismo según frequency. |
actions[] + range_strategy | Nodo del oponente (o sin hole_cards): la estrategia de rango completo, con las frecuencias de cada mano alineadas con actions; incluye range_hand_count. Se puede usar para ensamblar solver_results para la «conversión de rango». |
El BET_8 / RAISE_20 en un id de nodo es la cantidad absoluta de la apuesta (BB).
| HTTP | error | disparador / cómo solucionarlo |
|---|---|---|
| 400 | 1) invalid_board / invalid_positions; 2) missing_node / invalid_hole_cards | 1) board no tiene 3 cartas o hero/las posiciones no son válidas; 2) falta node o hole_cards no tiene 2 cartas. |
| 403 | invalid_node_token | (paso 2) el token node no es válido o no es tuyo — primero llama a /v1/gto/flop/tree para obtener el árbol. |
| 404 | no_solution | No hay solución preresuelta para este spot/board. |
Descargar: tree_request.jsontree_response.jsonnode_request.jsonnode_response.json
POST familia https://pokerai.bet/v1/gto/solver. Solucionador postflop puro, calculado en tiempo real, que usa una cuota de resolución independiente. La esencia es resolver a partir de la entrada: board + rangos oop/ip + pozo + stack restante + quién es Hero, sin necesidad de historial, por lo que puedes entrar desde cualquier spot. Tres pasos: programar → sondear el árbol → obtener la estrategia de un nodo.
Esquema completo de parámetros/respuesta y prueba en vivo → referencia interactiva (incluye /solver/tree, /solver/node).
la longitud de board establece la calle: 3=flop / 4=turn / 5=river. ⚠ La resolución en tiempo real comenzando en el flop tarda (flop SRP medido ~70 segundos) y no es adecuada para casos de uso que necesitan una respuesta rápida — si quieres un flop rápido, usa las «Soluciones preresueltas» de arriba (se sirven al instante en milisegundos); turn / river son más rápidos (de segundos a decenas de segundos).
# 1) programar (board 3/4/5 = flop/turn/river; flop ~70 segundos)
curl -s https://pokerai.bet/v1/gto/solver -H "Authorization: Bearer $POKERAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"board":"2c2h2s","oop_range":"AA,KK,QQ,AKs","ip_range":"JJ,TT,AQs,KQs","pot":7.5,"effective_stack":97,"hero":"OOP","bet_sizes":{"flop":[33,75],"turn":[67],"river":[75]},"raise_sizes":{"flop":[50],"turn":[80],"river":[125]},"donk_sizes":{"turn":[55],"river":[90]},"raise_limit":3}'
# 2) consultar el árbol hasta que spot_status=queryable; 3) obtener el nodo
curl -s https://pokerai.bet/v1/gto/solver/tree -H "Authorization: Bearer $POKERAI_API_KEY" \
-H "Content-Type: application/json" -d '{"solve":"eyJ..."}'
board | 3=flop / 4=turn / 5=river, p. ej. "2c2h2s9d" (turn). |
oop_range / ip_range | Obligatorio. Los rangos de los dos jugadores que entran en esta calle, cadenas de combinaciones ponderadas, p. ej. "AsKs:1,QQ:0.75,...". |
pot / effective_stack | Obligatorio. El bote y el stack efectivo restante (BB) al entrar en esta calle; determinan los tamaños de apuesta y deben ser reales. |
hero | Obligatorio: "OOP" o "IP". |
bet_sizes | Opcional: anula los tamaños de apuesta iniciales por calle, p. ej. {"flop":[33,75],"turn":[67],"river":[75]} (% del bote); si se omite flop, el valor predeterminado es 50%. |
raise_sizes | Opcional: anula los tamaños de subida por calle, p. ej. {"flop":[50],"turn":[80],"river":[125]} (% del bote); las calles omitidas reutilizan bet_sizes o los valores predeterminados. |
donk_sizes | Opcional: anula los tamaños de donk-lead de OOP, p. ej. {"turn":[55],"river":[90]} (% del bote); los valores predeterminados son 67% en turn y 100% en river. |
raise_limit | Opcional: límite de subidas para todo el árbol, 1–4; el valor predeterminado es 3 para resoluciones de flop/turn y 4 para resoluciones solo de river. |
// Solicitud (flop, con tamaños personalizados de apuesta / subida / donk)
{"board": "2c2h2s", "oop_range": "AA,KK,QQ,AKs", "ip_range": "JJ,TT,AQs,KQs", "pot": 7.5, "effective_stack": 97, "hero": "OOP", "bet_sizes": {"flop": [33,75], "turn": [67], "river": [75]}, "raise_sizes": {"flop": [50], "turn": [80], "river": [125]}, "donk_sizes": {"turn": [55], "river": [90]}, "raise_limit": 3}
// Respuesta (primera activación, consume 1 resolución)
{"status": "computing", "solve": "eyJ0Ijoic2x2XzJmMjk2MWU3Y2Y0ODU3OGUiLCJ1IjoiYjk4Y2Y5NzAtZTVjMS00Njk5LTg4ODQtOGQzYzcwMGIyNGJlIiwidHMiOjE3ODIxMjkxMTUyMDJ9.rtmeNcZoBNWJRhkAGkTSSR58ZafpAh35mi510bgPU6c", "solve_quota": {"used": 1, "limit": 100}}
| campo / caso | descripción |
|---|---|
solve | El identificador de la resolución, usado por los posteriores /tree y /node; el rango se proporciona solo una vez en este paso. |
status = computing | Se activó una nueva resolución y consume 1 cuota de resolución (consulta solve_quota). |
status = queryable | Ya existe una resolución en caché para este spot, sin cargo (sin campo solve_quota); consulta /tree directamente. |
429 status = busy | Todos los solucionadores están ocupados, sin cargo; vuelve a intentarlo más tarde. |
Resultado de caché (sin cargo de nuevo): volver a programar el mismo spot (mismo board/range/pot/stack/hero/bet_sizes/raise_sizes/donk_sizes/raise_limit) ya no consume cuota de resolución — si la respuesta no tiene el campo solve_quota significa que no se ha cobrado; simplemente usa el identificador solve devuelto para consultar /tree. Ejemplos: solicitud / respuesta.
POST https://pokerai.bet/v1/gto/solver/tree · lleva el identificador solve; consulta hasta que spot_status = queryable. Para llegar a una calle posterior, pasa las cartas repartidas: turn_card (una resolución de flop → un turn específico) y/o river_card. Un spot de river de una resolución de flop necesita AMBAS: turn_card + river_card (el river por sí solo no es único); una resolución de turn solo necesita river_card; omite ambas para la propia calle de la resolución.
// (2) obtener el árbol de esta calle (flop)
{"solve": "eyJ…"}
{"street": "flop", "spot_status": "queryable", "pot": 7.5, "effective_stack": 97, "solve_seconds": 25.84, "node_count": 14, "nodes": [{"node": "root", "is_hero": true, "status": "queryable", "token": "eyJ…"}, {"node": "root/BET 4.000000", "is_hero": false, "status": "queryable", "token": "eyJ…"}, {"node": "root/BET 4.000000/RAISE 12.000000", "is_hero": true, "status": "queryable", "token": "eyJ…"}, …]}
// árbol de turn (resolución de flop + turn_card)
{"solve": "eyJ…", "turn_card": "9d"}
{"street": "turn", "spot_status": "queryable", "pot": 7.5, "effective_stack": 97, "solve_seconds": 25.84, "node_count": 104, "nodes": [{"node": "root/BET 4.000000/CALL/9d", "is_hero": false, "status": "queryable", "token": "eyJ…"}, {"node": "root/BET 4.000000/CALL/9d/BET 10.000000", "is_hero": true, "status": "queryable", "token": "eyJ…"}, {"node": "root/BET 4.000000/CALL/9d/BET 10.000000/RAISE 34.000000", "is_hero": false, "status": "queryable", "token": "eyJ…"}, …]}
// árbol de river (resolución de flop + turn_card + river_card)
{"solve": "eyJ…", "turn_card": "9d", "river_card": "Qh"}
{"street": "river", "spot_status": "queryable", "pot": 7.5, "effective_stack": 97, "solve_seconds": 25.84, "node_count": 308, "nodes": [{"node": "root/BET 4.000000/CALL/9d/BET 10.000000/CALL/Qh", "is_hero": true, "status": "queryable", "token": "eyJ…"}, {"node": "root/BET 4.000000/CALL/9d/BET 10.000000/CALL/Qh/BET 27.000000", "is_hero": false, "status": "queryable", "token": "eyJ…"}, {"node": "root/BET 4.000000/CALL/9d/BET 10.000000/CALL/Qh/BET 27.000000/RAISE 83.000000", "is_hero": true, "status": "queryable", "token": "eyJ…"}, …]}
| campo | descripción |
|---|---|
spot_status | Estado de la resolución: available (no programada) / computing (resolviendo; sigue consultando) / queryable (se puede obtener) / expired (la entrada de caché se eliminó; vuelve a programar en el paso 1) / no_nodes (la resolución convergió, pero el runout/calle consultado no tiene nodos de decisión en el árbol — terminal; deja de consultar). |
nodes[] | Cada nodo de decisión: node (ruta de acción), is_hero, status, token (la credencial para obtener la estrategia de ese nodo, que se pasa al paso 3). El runout de river es un nodo de azar, que se navega mediante la carta de river. |
street / pot / effective_stack / node_count | Calle, bote, stack efectivo y número total de nodos de decisión. | Calle, bote y stack efectivo y número total de nodos de decisión. |
solve_seconds | Tiempo real transcurrido de esta resolución en tiempo real, desde la programación hasta la convergencia (segundos). Se devuelve solo cuando queryable; todos los runouts de la misma resolución comparten este valor. |
Esquema completo de parámetros y respuesta, y pruébalo en directo → referencia interactiva.
POST https://pokerai.bet/v1/gto/solver/node · lleva el token node. Un nodo Hero devuelve la estrategia de Hero; un nodo del oponente (o sin hole_cards) devuelve la estrategia de rango.
{"node": "eyJ…", "hole_cards": "AhKh"}
{"hole_cards": "AhKh", "node": "root", "is_hero": true, "strategy": [{"action": "check", "frequency": 0}, {"action": "bet", "amount_bb": 4, "sizing_pot": 0.5333, "frequency": 0.2666}, {"action": "bet", "amount_bb": 97, "sizing_pot": 12.9333, "allin": true, "frequency": 0.7334}]}
| campo | descripción |
|---|---|
is_hero | Indica si este nodo es la decisión de Hero. |
strategy[] | Nodo Hero: estrategia mixta de Hero para esta mano (action / amount_bb / sizing_pot (consulta tamaño de apuesta) / frequency), con allin: true añadido cuando va all-in. |
actions[] + range_strategy | Nodo del oponente (o sin hole_cards): en range_strategy, las frecuencias de cada mano se ajustan al orden de actions; también incluye range_hand_count. |
Esquema completo de parámetros y respuesta, y pruébalo en directo → referencia interactiva.
Cuando termines, puedes opcionalmente llamar a /v1/gto/solver/release para liberar el puerto de inmediato (de lo contrario, el sistema lo recupera automáticamente mediante TTL). Cuando la caché se ha liberado o sustituido por una resolución más reciente, este paso devuelve { "node_status": "expired" }; simplemente vuelve a programar en el paso 1. Un error de resolución por nodo devuelve { "node_status": "error", "message": … } (terminal: deja de consultar). Esquema completo de parámetros y respuesta de /solver/release → referencia interactiva.
| HTTP | error | desencadenante / cómo corregirlo |
|---|---|---|
| 400 | invalid_board / missing_range / invalid_pot / invalid_effective_stack / invalid_hero | (programación) el board, el rango oop/ip, el bote, el stack restante, Hero u otra entrada de resolución no es válida. |
| 400 | missing_solve / missing_node | (obtener árbol/nodo) falta el identificador solve o el token node. |
| 403 | invalid_solve / invalid_node_token | El identificador/token no es válido o no es tuyo: vuelve a programar / a obtener el árbol. |
| 429 | status: busy | Todos los solvers están ocupados, sin cargo; espera y vuelve a intentarlo. |
| 502 | solve_failed | No se pudo activar la resolución; vuelve a intentarlo más tarde. |
| 503 | upstream_unavailable | (árbol/nodo) no se puede acceder al solver después de los propios reintentos del servicio (error de transporte / 5xx): se puede reintentar. |
Descargar (turn, board=4): schedule_reqschedule_restree_reqtree_resnode_reqnode_res
Descargar (flop, board=3): schedule_reqschedule_restree_reqtree_resnode_reqnode_res
Descargar (river, board=5): schedule_reqschedule_restree_reqtree_resnode_reqnode_res
import requests, time
H = {"Authorization": "Bearer $POKERAI_API_KEY"}
BASE = "https://pokerai.bet/v1/gto"
# 1) programar (consume 1 cuota de resolución; gratis si hay acierto de caché)
solve = requests.post(f"{BASE}/solver", headers=H, json={
"board": "2c2h2s9d", "oop_range": "AA,KK,QQ,AKs", "ip_range": "JJ,TT,AQs,KQs",
"pot": 20, "effective_stack": 90, "hero": "OOP",
"bet_sizes": {"turn": [67], "river": [75]},
"raise_sizes": {"turn": [80], "river": [125]},
"donk_sizes": {"turn": [55], "river": [90]},
"raise_limit": 3}).json()["solve"]
# 2) consultar el árbol hasta que sea queryable
while True:
tree = requests.post(f"{BASE}/solver/tree", headers=H, json={"solve": solve}).json()
if tree["spot_status"] == "queryable": break
time.sleep(2) # calculando -> espera y vuelve a intentarlo
# 3) obtener la estrategia del nodo raíz de Hero
root = next(n for n in tree["nodes"] if n["node"] == "root")
strat = requests.post(f"{BASE}/solver/node", headers=H,
json={"node": root["token"], "hole_cards": "AhKh"}).json()
print(strat["strategy"])
POST https://pokerai.bet/v1/gto/range consume 1 general
Esquema completo de parámetros y respuesta, y pruébalo en directo → referencia interactiva.
Actualiza los rangos OOP/IP a lo largo de una línea de acción. Se usa principalmente para obtener el rango que llega a la siguiente calle (flop→turn / turn→river) y luego pasarlo a /v1/gto/solver. Todo el cálculo de actualización de rangos (incluidos la normalización y el descuento de faroles) lo realiza el solver y es coherente con los resultados del solver.
Este es un proxy de paso directo: tú ensamblas toda la entrada por tu cuenta, incluidos solver_results (el árbol de decisiones). El árbol de decisiones puede ser una de tus propias resoluciones o ensamblarse a partir del árbol de decisiones del flop de esta plataforma: llama a /v1/gto/flop/tree para obtener el rango inicial y, después, para cada nodo llama a /v1/gto/flop/node sin hole_cards para obtener la range_strategy completa, anidada como {node_type,player,strategy,childrens}. Consulta el script al final.
{
"range_oop": "AQs:1,AJs:0.48,...", // obligatorio, rango OOP inicial
"range_ip": "AA:1,AKs:1,...", // obligatorio, rango IP inicial
"solver_results": { /* obligatorio: el árbol de decisiones */ },
"node_id": "root/CHECK", // obligatorio, la línea de acción
"board": "2c2h2s", // opcional, cadena sin separadores (igual que otros endpoints)
"normalize": true, // opcional, el valor predeterminado es true
"explain": false, // opcional, explicación del cambio por mano
"track_hands": ["AA"], // opcional, rastrea solo estas manos
"bluff_discount_ratio": 0.8, // opcional, descuento de farol
"hero_position": "oop", // opcional, "oop" / "ip" — qué jugador es Hero (para el bloqueo de cartas)
"hero_hand": "AsKs" // opcional, elimina combinaciones que contienen las cartas de Hero (bloqueadores); se devuelve reflejado
}
Bloqueo de cartas (opcional): configura hero_position ("oop"/"ip") + hero_hand para eliminar de los rangos toda combinación que contenga una de las cartas de Hero — útil para el análisis rango contra mano. Ambos se devuelven reflejados en la respuesta. (Este par también se respeta en los wrappers de rango proyectado; /v1/gto/flop/projected-range admite además partner_hands.)
# solver_results es grande; colócalo en un archivo y usa -d @
curl -s https://pokerai.bet/v1/gto/range -H "Authorization: Bearer $POKERAI_API_KEY" \
-H "Content-Type: application/json" -d @range_request.json
{"bluff_combos_ratio": 0.33, "bluff_discount_ratio": 1, "board": ["2c", "2h", "2s"], "hand_bottom_ranks_ip": "KsQh:2413,KsQd:2413,KsQc:2413,KhQs:2413,…", "hand_bottom_ranks_oop": "KcJh:2414,KcTs:2415,KsTs:2415,KsTh:2415,…", "hand_ranks_ip": "QcQh:313,QdQh:313,QdQs:313,QhQs:313,QcQs:313,…", "hand_ranks_oop": "Ad2d:155,AdAc:311,AhAc:311,AhAd:311,AsAc:311,…", "node_id": "root/CHECK", "path_length": 1, "range_ip_new": "33:0.193023,44:0.216279,54s:0.65814,…", "range_ip_new_raw": "3c3d:0.193023,3c3h:0.193023,3c3s:0.193023,…", "range_ip_new_raw_before_normalization": "3c3d:0.166,3c3h:0.166,3c3s:0.166,3d3h:0.166,…", "range_oop_new": "33:0.245724,44:0.272975,54s:0.420008,…", "range_oop_new_raw": "3d3c:0.245857,3h3c:0.245847,3h3d:0.24586,…", "range_oop_new_raw_before_normalization": "3d3c:0.245843,3h3c:0.245833,3h3d:0.245845,…", "quota": {"used": 7, "limit": 100}}
| campo | descripción |
|---|---|
range_oop_new / range_ip_new | El rango actualizado normalizado (notación de clases), usado directamente como oop_range / ip_range de la siguiente calle que se envía al solver. |
range_oop_new_raw / range_ip_new_raw | El valor intermedio tras el descuento de farol, sin normalizar (notación de combinaciones); úsalo según sea necesario. |
range_oop_new_raw_before_normalization / range_ip_new_raw_before_normalization | El valor sin procesar, reducido solo a lo largo de la línea de acción, sin descuento de farol ni normalización. |
hand_ranks_oop / hand_ranks_ip | Clasificación de fuerza de mano (combo:rank; un valor menor es más fuerte). |
hand_bottom_ranks_oop / hand_bottom_ranks_ip | Clasificación del extremo inferior del rango. |
node_id / board / path_length | La línea de acción, el board y el número de pasos de la línea de acción devueltos como eco. |
bluff_discount_ratio / bluff_combos_ratio | Los parámetros de descuento de farol usados realmente esta vez. |
quota | Uso de la cuota general de este mes (used / limit). |
| HTTP | error | desencadenante / cómo corregirlo |
|---|---|---|
| 400 | missing_field | Falta uno de range_oop / range_ip / solver_results / node_id. |
| 400 | bad_request | El lado del solver lo rechazó (p. ej., el node_id no conduce a ningún lugar en el árbol de decisión que proporcionaste). |
Descargar: request.json (~1MB, incluye el árbol de decisión)response.jsonassemble_solver_results.py (script de principio a fin)
POST https://pokerai.bet/v1/gto/flop/projected-range consume 1 general
Esquema completo de parámetros y respuesta, y pruébalo en directo → referencia interactiva.
Reduce los rangos OOP/IP a lo largo de una línea de acción del flop para obtener directamente el rango inicial que entra en el turn. Proporciona el spot completo (board/pot_type/positions) y una línea de acción (node_id), y la plataforma ensambla automáticamente el árbol de decisiones en el servidor y completa la actualización del rango, devolviendo los mismos campos que la conversión de rango, además de un pot_type devuelto como eco.
Este es un wrapper de conveniencia sobre /v1/gto/range: te evita los pasos manuales de llamar a /v1/gto/flop/tree + /v1/gto/flop/node por nodo para ensamblar solver_results. Solo se aplica a líneas de acción del flop (el árbol de decisiones se ensambla a partir de los resultados presueltos del flop de esta plataforma); para turn→river, etc., donde debes aportar tu propio árbol de decisiones, sigue usando /v1/gto/range.
{
"board": "2c2h2s",
"pot_type": "SRP",
"positions": { "hero": "UTG", "raiser": "UTG", "caller": "BTN" },
"node_id": "root/BET_4",
"normalize": true,
"bluff_discount_ratio": 0.8,
"bluff_combos_ratio": 0.5,
"hero_position": "oop",
"hero_hand": "AsKs",
"partner_hands": ["Ac9c"]
}
| campo | descripción |
|---|---|
board | Obligatorio. El flop (cadena sin separadores, igual que en otros endpoints), p. ej. "2c2h2s". |
pot_type | Obligatorio. El tipo de bote, p. ej. "SRP". |
positions | Obligatorio. { hero, raiser, caller } (igual que en flop); los spots 3bet/limp pueden incluir three_bettor / limper. |
node_id | Opcional; el valor predeterminado es "root". La línea de acción del flop, usando la notación de API devuelta por /v1/gto/flop/tree (importe absoluto de la apuesta en BB), p. ej. "root/BET_4", "root/CHECK/BET_8/CALL". |
normalize | Opcional; el valor predeterminado es true. Indica si se debe normalizar el rango actualizado. |
bluff_discount_ratio / bluff_combos_ratio | Opcionales, cada uno en [0,1] (fuera de rango → 400). bluff_discount_ratio pondera los combos de farol de la parte inferior del rango; bluff_combos_ratio es la fracción del rango tratada como faroles. Omítelos para usar los valores predeterminados del servidor para turn/river. Ambos se devuelven como eco. |
hero_position / hero_hand | Bloqueo de cartas opcional. Establece hero_position ("oop"/"ip") + hero_hand (p. ej., "AsKs"): elimina del rango actualizado del villano cada combo que contenga una de las cartas de Hero (range_*_new_raw) y garantiza que la propia mano de Hero esté presente en su propio rango. Ambos se devuelven como eco. Solo se ve afectado range_*_new_raw; hand_ranks / hand_bottom_ranks se filtran únicamente por el board. |
partner_hands | Array opcional de combos de 4 caracteres (p. ej., ["Ac9c"]), requiere hero_position. Elimina del range_*_new_raw del villano cada combo que contenga una de esas cartas; modela cartas muertas conocidas (manos retiradas, cartas expuestas). Solo de entrada (no se devuelve como eco). También se admite en /v1/gto/turn/projected-range. |
flop_version | Opcional. Qué conjunto de datos de flop (uno resuelto por versión preflop): 6max (predeterminado) / 6max_RC_100bb_200NL / 6max_RC_100bb_100NL / 6max_RC_40bb. Omítelo para usar el predeterminado (6max); si esa versión no tiene datos para el spot, degrada de forma segura a 6max; un valor desconocido -> 400 unsupported_flop_version. Es independiente de preflop_version. |
curl -s https://pokerai.bet/v1/gto/flop/projected-range -H "Authorization: Bearer $POKERAI_API_KEY" \
-H "Content-Type: application/json" -d @projected_range_request.json
{"board": ["2c", "2h", "2s"], "pot_type": "SRP", "node_id": "root/BET_4", "bluff_combos_ratio": 0.5, "bluff_discount_ratio": 0.8, "hero_position": "oop", "hero_hand": "AsKs", "hand_bottom_ranks_ip": "AhTh:2405,AsTs:2405,Ac9c:2406,Ad9d:2406,…", "hand_bottom_ranks_oop": "AhJs:2404,AsJc:2404,AsJd:2404,AsJh:2404,…", "hand_ranks_ip": "QcQd:313,QcQh:313,QcQs:313,QdQh:313,…", "hand_ranks_oop": "Ad2d:155,AdAc:311,AdAh:311,AdAs:311,…", "path_length": 1, "range_ip_new": "33:0.193023,44:0.216279,54s:0.65814,55:0.344186,…", "range_ip_new_raw": "3c3d:0.193023,3c3h:0.193023,3c3s:0.193023,3d3h:0.193023,…", "range_ip_new_raw_before_normalization": "3c3d:0.166,3c3h:0.166,3c3s:0.166,3d3h:0.166,…", "range_oop_new": "44:0.0120032,55:0.0422217,66:0.181192,77:0.327323,…", "range_oop_new_raw": "4s4c:0.0666554,4s4h:0.0666554,5d5c:0.005,5d5h:0.005,…", "range_oop_new_raw_before_normalization": "4s4c:0.011816,4s4h:0.011816,5s5c:0.0392591,5s5h:0.0392591,…", "quota": {"used": 7, "limit": 100}}
| campo | descripción |
|---|---|
range_oop_new / range_ip_new | El rango actualizado normalizado (notación de clases), usado directamente como oop_range / ip_range de la siguiente calle que se envía al solver. |
range_oop_new_raw / range_ip_new_raw | El valor intermedio tras el descuento de farol, sin normalizar (notación de combinaciones); úsalo según sea necesario. |
range_oop_new_raw_before_normalization / range_ip_new_raw_before_normalization | El valor sin procesar, reducido solo a lo largo de la línea de acción, sin descuento de farol ni normalización. |
hand_ranks_oop / hand_ranks_ip | Clasificación de fuerza de mano (combo:rank; un valor menor es más fuerte). |
hand_bottom_ranks_oop / hand_bottom_ranks_ip | Clasificación del extremo inferior del rango. |
node_id / board / pot_type / path_length | La línea de acción, el board, el tipo de bote y el número de pasos de la línea de acción devueltos como eco. |
bluff_discount_ratio / bluff_combos_ratio | Los parámetros de descuento de farol usados realmente esta vez. |
quota | Uso de la cuota general de este mes (used / limit). |
| HTTP | error | desencadenante / cómo corregirlo |
|---|---|---|
| 400 | invalid_board / invalid_positions | el board no tiene 3 cartas o positions.hero no es válido. |
| 404 | no_solution (y un errorType del servidor como no_ranges / no_root_node) | No hay un árbol de flop preresuelto para este spot, o la línea de acción node_id no lleva a ningún sitio. |
Descargar: request.jsonresponse.json
POST https://pokerai.bet/v1/gto/turn/projected-range gratis
Esquema completo de parámetros y respuesta, y pruébalo en directo → referencia interactiva.
La versión turn→river del rango proyectado de flop, para una resolución de turn en tiempo real. Reduce los rangos a lo largo de una línea de acción de turn (incluido el CALL/CHECK que cierra la calle) para obtener directamente el rango inicial que entra en river. Los rangos OOP/IP al entrar en turn se leen de la propia configuración de la resolución (los rangos con los que se programó mediante /v1/gto/solver), por lo que solo pasas el identificador de resolución solve + un node_id. Gratis (la resolución ya se cobró mediante /v1/gto/solver), como /v1/gto/solver/tree; devuelve los mismos campos que la conversión de rango.
Primero consulta /v1/gto/solver/tree hasta que spot_status = queryable. Para turn→river no ensamblas solver_results manualmente (la plataforma lo lee de la resolución y lo ensambla).
{
"solve": "eyJ…",
"node_id": "root/CHECK/BET 6.000000/CALL",
"normalize": true,
"bluff_discount_ratio": 0.8,
"hero_position": "oop",
"hero_hand": "AsKs"
}
| campo | descripción |
|---|---|
solve | Obligatorio. El identificador de resolución devuelto por /v1/gto/solver (una resolución de turn). |
node_id | Obligatorio. Una línea de acción de turn, puede terminar en el CALL/CHECK que cierra la calle. Notación de nodo del solucionador (con espacios), p. ej., "root/CHECK/BET 6.000000/CALL" (de los nodos de /v1/gto/solver/tree). |
normalize | Opcional; el valor predeterminado es true. Indica si se debe normalizar el rango actualizado. |
bluff_discount_ratio | Opcional. Descuento de faroles (0..1). |
hero_position / hero_hand | Bloqueo de cartas opcional: establecer hero_position ("oop"/"ip") + hero_hand (p. ej., "AsKs") elimina del rango actualizado del villano cada combinación que contenga una de las cartas de Hero. |
partner_hands | Matriz opcional de combinaciones de 4 caracteres (p. ej., ["Ac9c"]), requiere hero_position. Elimina de range_*_new_raw del villano cada combinación que contenga una de esas cartas. Solo de entrada. |
curl -s https://pokerai.bet/v1/gto/turn/projected-range -H "Authorization: Bearer $POKERAI_API_KEY" \
-H "Content-Type: application/json" -d @turn_projected_range_request.json
{"bluff_combos_ratio": 0.33, "bluff_discount_ratio": 1, "board": ["8d", "4h", "8s", "Qc"], "hand_bottom_ranks_ip": "TcTs:2943,TdTh:2943,TdTs:2943,9h9s:3020,…", "hand_bottom_ranks_oop": "AhKd:4646,AhKc:4646,AcKh:4646,JsTs:4746,…", "hand_ranks_ip": "Ac8c:2007,Ah8h:2007,KcKs:2645,KhKs:2645,…", "hand_ranks_oop": "8c8h:85,Ah8h:2007,Ac8c:2007,9c8c:2029,…", "node_id": "root/CHECK/BET 6.000000/CALL", "path_length": 3, "range_ip_new": "99:0.603064,A8s:0.5,AKs:0.70197,AQs:0.453337,…", "range_ip_new_raw": "9c9d:0.71487,9c9h:0.394271,9c9s:0.71487,…", "range_ip_new_raw_before_normalization": "9c9d:0.714699,9c9h:0.394176,9c9s:0.714699,…", "range_oop_new": "88:0.131148,98s:0.0902494,A8s:0.0344418,…", "range_oop_new_raw": "8c8h:0.777777,9c8c:0.185048,9h8h:0.17177,…", "range_oop_new_raw_before_normalization": "8c8h:0.418968,9c8c:0.0996806,9h8h:0.0925282,…"}
| campo | descripción |
|---|---|
range_oop_new / range_ip_new | El rango normalizado que entra al river (notación de clases), usado directamente como oop_range / ip_range de la resolución del river. |
range_*_raw / range_*_raw_before_normalization | Los valores intermedios sin normalizar / previos al descuento (notación de combinaciones). |
hand_ranks_* / hand_bottom_ranks_* | Clasificación de fuerza de mano / clasificación del extremo inferior del rango (combo:rank; cuanto menor, más fuerte). |
node_id / board / path_length | La línea de acción repetida, el board (4 cartas) y el número de pasos de la línea de acción. |
bluff_discount_ratio / bluff_combos_ratio | Los parámetros de descuento de farol usados realmente esta vez. |
Nota: es gratis, por lo que la respuesta no tiene el campo quota; tampoco pot_type (solo para flop).
| HTTP | error / estado | desencadenante / cómo corregirlo |
|---|---|---|
| 200 | { "spot_status": "computing" } | La resolución aún no ha convergido; sigue consultando /v1/gto/solver/tree hasta que sea queryable. |
| 400 | missing_solve / missing_node_id | Falta el identificador solve o node_id. |
| 410 | expired | La resolución caducó (TTL); vuelve a programarla mediante /v1/gto/solver. |
| 502 | no_solution, etc. | Error de resolución del servicio ascendente. |
Descargar: request.jsonresponse.json
POST https://pokerai.bet/v1/gto/evs gratis
Esquema completo de parámetros y respuesta; pruébalo en directo → referencia interactiva.
Valores esperados por mano y por acción en un nodo de una resolución completada. Proporciona el identificador de resolución solve (de /v1/gto/solver) + un node_id (de /v1/gto/solver/tree); hand opcional filtra a una mano. Gratis (la resolución ya se cobró). Primero consulta /v1/gto/solver/tree hasta spot_status = queryable.
{
"solve": "eyJ0Ijoic2x2X3h4eXoi...(identificador de /v1/gto/solver)",
"node_id": "root",
"hand": "2c2d"
}
| campo | descripción |
|---|---|
solve | Obligatorio. El identificador de resolución de /v1/gto/solver. |
node_id | Obligatorio. Un nodo de /v1/gto/solver/tree (notación del solver; p. ej., "root", "root/CHECK/BET 6.000000"). |
hand | Opcional. Filtra a los EV de una mano (p. ej., "2c2d"); omítelo para todas las manos. |
actions){"node_id": "root", "task_id": "slv_srp_…", "player": 1, "round": "FLOP", "actions": ["CHECK", "BET 4.000000", "BET 97.000000"], "evs": {"2c2d": [-0.826359, -0.792223, -1.643411], "2c2h": […], …}}
| campo | descripción |
|---|---|
actions | Las acciones del nodo en orden; la matriz de EV de cada mano se alinea con ellas. |
evs | Por mano → matriz del EV de cada acción (bb). Con hand, evs es una única matriz para esa mano. |
player / round / node_id / task_id | Qué jugador actúa, la calle y el identificador repetido de nodo / resolución. |
Nota: es gratis, por lo que no hay campo quota. Devuelve { "spot_status": "computing" } si la resolución no ha convergido (consulta /v1/gto/solver/tree).
Uniendo los endpoints: una mano SRP (UTG abre, BTN paga), Hero = UTG. Los curls siguientes omiten el encabezado de autenticación (igual que en Inicio rápido).
POST /v1/gto/preflop
{ "hole_cards": "AdKd", "positions": { "hero": "UTG" },
"preflop_actions": [ { "position": "SB", "action": "small blind", "amount": 0.5 }, { "position": "BB", "action": "big blind", "amount": 1 } ] }
Solo las ciegas de SB + BB (sin subidas) = Hero es el primero en actuar (una situación de apertura). Devuelve la frecuencia y el tamaño de apertura.
Flop 2c2h2s. El flop es un árbol de decisiones, dos pasos: primero obtén el árbol y luego usa el token del nodo de Hero para obtener la estrategia.
// 1) obtener el árbol (no se necesitan hole_cards)
POST /v1/gto/flop/tree
{ "board": "2c2h2s", "pot_type": "SRP",
"positions": { "hero": "UTG", "raiser": "UTG", "caller": "BTN" } }
// → en nodes[], root (is_hero:true) contiene un token
// 2) usar el token de root para obtener la estrategia de Hero
POST /v1/gto/flop/node
{ "node": "<token de root>", "hole_cards": "AdKd" }
La primera decisión de Hero = root; si se enfrenta a una apuesta / actúa por segunda vez → selecciona el nodo is_hero:true correspondiente. Consulta el árbol de decisiones del flop.
El turn (p. ej., 9d) necesita una resolución en tiempo real, que requiere los rangos de ambos jugadores al llegar al turn. Obtenlos con el árbol de decisiones del flop + conversión de rangos:
/v1/gto/flop/tree para los oop_range / ip_range iniciales y los nodos de decisión.root/CHECK/BET_8/CALL), llama a /v1/gto/flop/node para cada nodo (sin hole_cards) para obtener range_strategy y ensamblar solver_results — consulta el script assemble_solver_results.py en la sección de conversión de rangos./v1/gto/range se actualiza a lo largo de esa línea → range_oop_new / range_ip_new son los rangos que entran en el turn.queryable y, después, obtén el nodo:
POST /v1/gto/solver
{ "board": "2c2h2s9d", "oop_range": "<rango OOP al llegar al turn>", "ip_range": "<rango IP al llegar al turn>",
"pot": <bote del turn>, "effective_stack": <stack efectivo del turn>, "hero": "OOP" }
¿Ya tienes tu propio rango/situación? En el paso 3 proporciona oop_range / ip_range directamente y omite la derivación.
El river (board con 5 cartas) es igual que el turn: puedes resolverlo de forma independiente (proporciona directamente el rango que entra en el river), o usar la conversión de rangos para actualizar una vez más la línea de acción del turn, obtener el rango que entra en el river y después proporcionarlo al solver.
Envuelve pokerkit-plus (un superconjunto de pokerkit 0.7.3): semántica de board/mano, rangos y equity, eval/equity/ICM/notación y simulación de partidas. Reutiliza la misma API key y cuota — los endpoints económicos cargan al bucket general, y los endpoints Monte-Carlo al bucket solve. Ruta base /v1/pokerkit/*; las entradas de cartas son cadenas sin separadores (AsKsQs), los enums devuelven {name,value}. Parámetros/esquema completos por endpoint y prueba en directo → referencia interactiva; especificación legible por máquina → /openapi.en.json (instantánea combinada de GTO + pokerkit).
Board (independiente de Hero): /texture (humedad/conectividad/proyectos disponibles), /nuts (nuts + combos que empatan), /category-combos, /board-report (textura+nuts). Hero: /hand-tier (nivel de mano formada), /draws, /outs, /blockers, /hand-report (textura+nivel+proyectos+outs en una llamada).
| campo | descripción |
|---|---|
board | Obligatorio. 3/4/5 cartas comunitarias, sin separadores; p. ej., "AsKsQs". |
hole | Obligatorio para los endpoints de Hero (hand-tier / draws / outs / blockers / hand-report). 2 cartas ocultas, p. ej., "JhTh"; los endpoints de board (texture / nuts / category-combos / board-report) lo omiten. |
hand_type | Opcional; el valor predeterminado es StandardHighHand (solo v1; otros tipos devuelven 400). |
dead | Opcional. Cartas muertas / retiradas (aceptadas por todos los endpoints de este grupo). |
POST https://pokerai.bet/v1/pokerkit/texture — Estructura del board: humedad/conectividad/franja de valores/disponibilidad de proyectos/forma de palos. Parámetros completos / pruébalo en directo →
{"board": "AsKsQs"}
{"result": {"cards": ["As", "Ks", "Qs"], "wetness": {"name": "WET", "value": "Wet"}, "connectivity": {"name": "HIGH", "value": "High"}, "rank_band": {"name": "HIGH", "value": "High"}, "straight_draw": {"name": "OPEN_ENDED", "value": "Open-ended"}, "flush_draw": {"name": "LIVE", "value": "Live"}, "are_two_tone": false, "are_monotone": true, "are_rainbow": false}}
POST https://pokerai.bet/v1/pokerkit/nuts — La mano más fuerte que se puede formar + todos los combos de dos cartas que empatan (con is_royal / board_is_nuts). Parámetros completos / pruébalo en directo →
{"board": "AsKsQs"}
{"result": {"hand": "TsJsKsQsAs", "combos": [{"cards": ["Ts", "Js"], "hand": "TsJsKsQsAs", "as_frozenset": ["Js", "Ts"]}], "candidate_count": 1176, "board_is_nuts": false, "is_royal": true, "label": {"name": "STRAIGHT_FLUSH", "value": "Straight flush"}}}
POST https://pokerai.bet/v1/pokerkit/category-combos — Cada combo activo de dos cartas agrupado por categoría formada. Parámetros completos / pruébalo en directo →
{"board": "AsKsQs"}
{"result": {"by_category": {"HIGH_CARD": [{"cards": ["2c", "3c"], "hand": "2c3cKsQsAs", "as_frozenset": ["2c", "3c"]}, {"cards": ["2c", "3d"], "hand": "2c3dKsQsAs", "as_frozenset": ["2c", "3d"]}], …}}}
POST https://pokerai.bet/v1/pokerkit/board-report — textura + nuts en una llamada (resumen del board). Parámetros completos / pruébalo en directo →
{"board": "AsKsQs"}
{"result": {"texture": {"cards": ["As", "Ks", "Qs"], "wetness": {"name": "WET", "value": "Wet"}, "connectivity": {"name": "HIGH", "value": "High"}, "rank_band": {"name": "HIGH", "value": "High"}, "straight_draw": {"name": "OPEN_ENDED", "value": "Open-ended"}, "flush_draw": {"name": "LIVE", "value": "Live"}, "are_two_tone": false, "are_monotone": true, "are_rainbow": false}, "nuts": {"hand": "TsJsKsQsAs", "combos": [{"cards": ["Ts", "Js"], "hand": "TsJsKsQsAs", "as_frozenset": ["Js", "Ts"]}], "candidate_count": 1176, "board_is_nuts": false, "is_royal": true, "label": {"name": "STRAIGHT_FLUSH", "value": "Straight flush"}}}}
POST https://pokerai.bet/v1/pokerkit/hand-tier — Nivel de mano formada de Hero (pareja / dobles parejas / trío / niveles de kicker, is_nut). Parámetros completos / pruébalo en directo →
{"hole": "JhTh", "board": "AsKsQs"}
{"result": {"category": {"name": "STRAIGHT", "value": "Straight"}, "is_nut": false, "pair_tier": null, "two_pair_tier": null, "three_of_a_kind_tier": null, "kicker_tier": null, "nut_rank": {"name": "NON_NUT", "value": "Non-nut"}}}
POST https://pokerai.bet/v1/pokerkit/draws — Proyectos de Hero (proyecto de escalera / color, rango de nuts). Parámetros completos / pruébalo en directo →
{"hole": "Ah5h", "board": "Kh7h2c"}
{"result": {"straight_draw": null, "flush_draw": {"name": "LIVE", "value": "Live"}, "nut_rank": {"name": "NUT", "value": "Nut"}}}
POST https://pokerai.bet/v1/pokerkit/outs — Outs de Hero que mejoran la categoría formada, agrupados + cantidad. Parámetros completos / pruébalo en directo →
{"hole": "Ah5h", "board": "Kh7h2c"}
{"result": {"by_category": {"ONE_PAIR": ["2d", "2s", "5c", "5d", "5s", "7c", "7d", "7s", "Kc", "Kd", "Ks", "Ac", "Ad", "As"], "FLUSH": ["2h", "3h", "4h", "6h", "8h", "9h", "Th", "Jh", "Qh"]}, "count": 23}}
POST https://pokerai.bet/v1/pokerkit/blockers — Cuántos combos de nuts bloquea Hero (cartas bloqueadoras / fracción). Parámetros completos / pruébalo en directo →
{"hole": "AhAd", "board": "AsKsQs"}
{"result": {"nut_combos_total": 1, "nut_combos_blocked": 0, "blocker_cards": [], "block_fraction": 0.0, "blocks_nuts": false}}
POST https://pokerai.bet/v1/pokerkit/hand-report — textura + nivel + proyectos + outs en una llamada (resumen de Hero, principal). Parámetros completos / pruébalo en directo →
{"hole": "JhTh", "board": "AsKsQs"}
{"result": {"texture": {"cards": ["As", "Ks", "Qs"], "wetness": {"name": "WET", "value": "Wet"}, "connectivity": {"name": "HIGH", "value": "High"}, "rank_band": {"name": "HIGH", "value": "High"}, "straight_draw": {"name": "OPEN_ENDED", "value": "Open-ended"}, "flush_draw": {"name": "LIVE", "value": "Live"}, "are_two_tone": false, "are_monotone": true, "are_rainbow": false}, "tier": {"category": {"name": "STRAIGHT", "value": "Straight"}, "is_nut": false, "pair_tier": null, "two_pair_tier": null, "three_of_a_kind_tier": null, "kicker_tier": null, "nut_rank": {"name": "NON_NUT", "value": "Non-nut"}}, "draws": {"straight_draw": null, "flush_draw": null, "nut_rank": null}, "outs": {"by_category": {}, "count": 0}}}
/range/expand (notación → combos concretos), /range/value (rango de valor según el umbral de categoría formada; aggression ∈ NO_BET/SINGLE_BET/RAISED), /range/nut-advantage (proporción exacta de nuts, sin muestreo).
| campo | descripción |
|---|---|
notation | (expand) matriz de notación de rangos; p. ej., ["AA","KQs","QQ+"]. |
hero / villain | (nut-advantage) una matriz de notación de rangos para cada uno. |
board | Cartas comunitarias (obligatorias para value / nut-advantage; expand lo omite). |
aggression | (valor) NO_BET / SINGLE_BET / RAISED establece el mínimo de la categoría; o use floor para establecerlo explícitamente. |
POST https://pokerai.bet/v1/pokerkit/range/expand — Expande la notación de rango en combinaciones concretas de dos cartas. Parámetros completos / pruébalo en directo →
{"notation": ["AA", "KQs"]}
{"result": [["Ac", "Ad"], ["Ac", "Ah"], ["Ac", "As"], ["Ad", "Ah"], ["Ad", "As"], ["Ah", "As"], ["Kc", "Qc"], ["Kd", "Qd"], ["Kh", "Qh"], ["Ks", "Qs"]]}
POST https://pokerai.bet/v1/pokerkit/range/value — Construye un rango de valor según el mínimo de categoría formada (agresión). Parámetros completos / pruébalo en directo →
{"board": "AsKsQs", "aggression": "SINGLE_BET"}
{"result": [["2s", "3s"], ["2s", "4s"], ["2s", "5s"], ["2s", "6s"], ["2s", "7s"], ["2s", "8s"], …]}
POST https://pokerai.bet/v1/pokerkit/range/nut-advantage — División exacta de la proporción de nuts por recuento de combinaciones (sin muestreo, determinista). Parámetros completos / pruébalo en directo →
{"hero": ["AA", "KK"], "villain": ["QQ", "JJ"], "board": "AsKsQs"}
{"result": {"hero_share": 0.5, "villain_share": 0.5, "basis": {"name": "NUT_SHARE", "value": "Nut share"}}}
consume 1 general /eval/hand, /eval/compare (clasificación + empates), /icm (determinista), /notation/parse (.phh → estructurado). consume 1 solve Monte-Carlo: /equity, /hand-strength, /range/equity-advantage — con sample_count (limitado) y seed (reproducible, ~2 s a 10k).
Los endpoints de Monte-Carlo (equity / hand-strength / range/equity-advantage) consumen el cupo de solve; el resto consume general.
| campo | descripción |
|---|---|
hole / holdings / board | Entradas de evaluación: un único hole + board (eval/hand), o varios holdings (2+) + board (eval/compare). |
ranges / hole_range / hero / villain | Notación de rango (equity / hand-strength / range/equity-advantage). |
sample_count / seed | Monte-Carlo: cantidad de muestras (limitada; por encima del límite se ajusta al máximo) / semilla de RNG (reproducible). |
payouts / chips | (icm) estructura de pagos / fichas por jugador. |
text | (notation/parse) una cadena de historial de manos .phh. |
POST https://pokerai.bet/v1/pokerkit/eval/hand — Evalúa hole + board para obtener una mano formada (5 cartas + etiqueta de categoría). Parámetros completos / pruébalo en directo →
{"hole": "JhTh", "board": "AsKsQs"}
{"result": {"hand": "JhThAsKsQs", "label": {"name": "STRAIGHT", "value": "Straight"}}}
POST https://pokerai.bet/v1/pokerkit/eval/compare — Clasifica 2+ holdings en un board (con empates). Parámetros completos / pruébalo en directo →
{"holdings": ["AcAd", "KsKh", "JhTh"], "board": "AsKsQs"}
{"result": [{"index": 2, "hole": "JhTh", "hand": "JhThAsKsQs", "rank": 1, "label": {"name": "STRAIGHT", "value": "Straight"}}, {"index": 0, "hole": "AcAd", "hand": "AcAdAsKsQs", "rank": 2, "label": {"name": "THREE_OF_A_KIND", "value": "Three of a kind"}}, {"index": 1, "hole": "KsKh", "hand": "KsKhAsKsQs", "rank": 3, "label": {"name": "THREE_OF_A_KIND", "value": "Three of a kind"}}]}
POST https://pokerai.bet/v1/pokerkit/equity — Equity de varios rangos en un board (Monte-Carlo). Parámetros completos / pruébalo en directo →
{"ranges": [["AA"], ["KK"]], "board": "", "sample_count": 2000, "seed": 7}
{"result": {"equities": [0.8235, 0.1765], "sample_count": 2000}}
POST https://pokerai.bet/v1/pokerkit/hand-strength — Fracción de victorias de Hero frente a N jugadores (Monte-Carlo). Parámetros completos / pruébalo en directo →
{"hole_range": ["AhKh"], "board": "Qh7c2d", "player_count": 3, "sample_count": 2000, "seed": 7}
{"result": {"hand_strength": 0.3945, "player_count": 3, "sample_count": 2000}}
POST https://pokerai.bet/v1/pokerkit/icm — División de equity de ICM a partir de fichas / pagos (determinista). Parámetros completos / pruébalo en directo →
{"payouts": [50, 30, 20], "chips": [5000, 3000, 2000]}
{"result": {"icm": [38.392857142857146, 32.75, 28.857142857142854]}}
POST https://pokerai.bet/v1/pokerkit/range/equity-advantage — División de la cuota de equity entre dos rangos (Monte-Carlo). Parámetros completos / pruébalo en directo →
{"hero": ["AA", "KK"], "villain": ["QQ", "JJ"], "board": "AsKsQs", "sample_count": 2000, "seed": 7}
{"result": {"hero_share": 0.80325, "villain_share": 0.19675, "basis": {"name": "EQUITY", "value": "Equity"}, "sample_count": 2000}}
POST https://pokerai.bet/v1/pokerkit/notation/parse — Analiza un historial de manos .phh para obtener una configuración estructurada (variante / ciegas / stacks / acciones…). Parámetros completos / pruébalo en directo →
{"text": "variant = \"NT\"\nante_trimming_status = true\nantes = [0, 0]\nblinds_or_straddles = [1, 2]\nmin_bet = 2\nstarting_stacks = [200, 200]\nactions = [\"d dh p1 AhKh\", \"d dh p2 QsQd\", \"p1 cbr 6\", \"p2 cc\", \"d db Qh7c2d\"]\n"}
{"result": {"variant": "NT", "ante_trimming_status": true, "antes": [0, 0], "blinds_or_straddles": [1, 2], "bring_in": null, "small_bet": null, "big_bet": null, "min_bet": 2, "starting_stacks": [200, 200], "actions": ["d dh p1 AhKh", "d dh p2 QsQd", "p1 cbr 6", "p2 cc", "d db Qh7c2d"], "automations": [{"name": "ANTE_POSTING", "value": "Ante posting"}, …], "author": null, "event": null, "day": null, "month": null, "year": null, "hand": null, "currency": null}}
Reproducción sin estado y con información completa: el cliente lleva la lista de acciones; el servidor reconstruye el estado con pokerkit (estado de servidor cero). /games/state (instantánea del punto actual), /games/step (aplica next_action; expected_action_count es un token de concurrencia optimista; discrepancia → 409), /notation/replay (configuración o texto .phh → instantáneas por paso), /cards/normalize (valida/normaliza una cadena de cartas).
| campo | descripción |
|---|---|
variant | Obligatorio. Código de variante, por ejemplo, "NT" (hold'em sin límite); lista completa en /v1/pokerkit/meta. |
antes / starting_stacks | Obligatorio. Antes / stacks iniciales por jugador (matrices de enteros). |
blinds_or_straddles / min_bet | Ciegas / straddles; min_bet es obligatorio para no-limit / pot-limit (fixed-limit / stud usan small_bet / big_bet / bring_in). |
actions | Lista de acciones hasta ahora (notación de pokerkit: d dh p1 AhKh repartir cartas privadas, p2 cbr 6 subir a 6, p1 cc pasar/igualar, p1 f retirarse). |
next_action / expected_action_count | (paso) acción que aplicar / token de concurrencia (= longitud de la lista que amplías; discrepancia → 409). |
text / index | (repetición) un texto .phh en su lugar; index devuelve solo ese paso. cards/normalize acepta solo cards (una cadena de cartas). |
POST https://pokerai.bet/v1/pokerkit/games/state — Lista de acciones → instantánea del punto actual (se muestran todas las cartas privadas). Parámetros completos / pruébalo en vivo →
{"variant": "NT", "antes": [0, 0], "blinds_or_straddles": [1, 2], "min_bet": 2, "starting_stacks": [200, 200], "actions": ["d dh p1 AhKh", "d dh p2 QsQd", "p2 cbr 6"]}
{"result": {"snapshot": {"terminal": false, "street_index": 0, "actor_index": 0, "pot": 8, "bets": [2, 6], "stacks": [198, 194], "board": [], "hole_cards": [{"player": 0, "cards": ["Ah", "Kh"]}, {"player": 1, "cards": ["Qs", "Qd"]}], "legal_actions": [{"action": "fold"}, {"action": "check_or_call", "amount": 4}, {"action": "complete_bet_or_raise_to", "min": 10, "max": 200}]}, "actions": ["d dh p1 AhKh", "d dh p2 QsQd", "p2 cbr 6"]}}
POST https://pokerai.bet/v1/pokerkit/games/step — Aplica next_action → nueva instantánea (token de concurrencia; 409 si no coincide). Parámetros completos / pruébalo en vivo →
{"variant": "NT", "antes": [0, 0], "blinds_or_straddles": [1, 2], "min_bet": 2, "starting_stacks": [200, 200], "actions": ["d dh p1 AhKh", "d dh p2 QsQd", "p2 cbr 6"], "next_action": "p1 cc", "expected_action_count": 3}
{"result": {"snapshot": {"terminal": false, "street_index": 1, "actor_index": null, "pot": 12, "bets": [0, 0], "stacks": [194, 194], "board": [], "hole_cards": [{"player": 0, "cards": ["Ah", "Kh"]}, {"player": 1, "cards": ["Qs", "Qd"]}], "legal_actions": [{"action": "deal_board"}]}, "actions": ["d dh p1 AhKh", "d dh p2 QsQd", "p2 cbr 6", "p1 cc"]}}
POST https://pokerai.bet/v1/pokerkit/notation/replay — configuración o .phh → instantáneas por paso (índice opcional para un solo paso). Parámetros completos / pruébalo en vivo →
{"variant": "NT", "antes": [0, 0], "blinds_or_straddles": [1, 2], "min_bet": 2, "starting_stacks": [200, 200], "actions": ["d dh p1 AhKh", "d dh p2 QsQd", "p2 cbr 6", "p1 f"], "index": 2}
{"result": {"snapshot": {"terminal": false, "street_index": 0, "actor_index": 1, "pot": 3, "bets": [2, 1], "stacks": [198, 199], "board": [], "hole_cards": [{"player": 0, "cards": ["Ah", "Kh"]}, {"player": 1, "cards": ["Qs", "Qd"]}], "legal_actions": [{"action": "fold"}, {"action": "check_or_call", "amount": 1}, {"action": "complete_bet_or_raise_to", "min": 4, "max": 200}]}, "step_count": 5}}
POST https://pokerai.bet/v1/pokerkit/cards/normalize — Valida / normaliza una cadena de cartas a cartas estándar de 2 caracteres. Parámetros completos / pruébalo en vivo →
{"cards": "Ah Ks Qs"}
{"result": ["Ah", "Ks", "Qs"]}
También GET /v1/pokerkit/meta (versiones / códigos de variante / tipos de mano / vocabularios de enumeración). Esquema completo de parámetros y pruébalo en vivo para cada endpoint → referencia interactiva (explora ambas API desde la parte superior).
Un resumen de la solicitud/respuesta completa de cada endpoint (datos reales, sin campos omitidos) está en la «Descarga» de cada sección anterior, o: preflop · árbol de flop · nodo de flop · solucionador · rango · rango proyectado · respuesta de rango proyectado · script de ensamblaje.
/v1 de la ruta es la versión principal. Los cambios incompatibles (eliminar/cambiar campos, cambiar la semántica) pasan a una nueva versión principal /v2, y /v1 sigue disponible./v1 sin aviso por separado — analiza ignorando los «campos desconocidos» y no valides estrictamente mediante una lista permitida los campos de respuesta.| fecha | cambio |
|---|---|
| 2026-07-22 | /v1/gto/solver ahora acepta los campos independientes raise_sizes, donk_sizes y raise_limit, además de bet_sizes. |
| 2026-07-12 | Se añadió POST /v1/gto/solver/release — libera antes de tiempo el puerto del pool de una resolución para que vuelva al pool inmediatamente en lugar de esperar a que expire el TTL de la caché (opcional, gratuito; llama después de tu último /solver/tree / /solver/node de esa resolución). |
| 2026-07-04 | Se añadió /v1/gto/evs (EV de nodo por mano y por acción de una resolución completada); /v1/gto/turn/projected-range ahora también admite partner_hands. |
| 2026-07-04 | /v1/gto/flop/projected-range ahora respeta bluff_discount_ratio / bluff_combos_ratio de la solicitud, inserta la propia mano de Hero en el rango de Hero y añade partner_hands (bloquea las cartas muertas del compañero del rango del villano). |
| 2026-06-22 | Se añadió la API de motor de póker / semántica /v1/pokerkit/* (semántica de mesa/mano, rangos/equity, eval/equity/ICM/notation, simulación de partidas; misma clave y cuota). Consulta abajo. |
| 2026-06-22 | Se añadió /v1/gto/preflop/range (todo el rango preflop de 13×13, 169 manos en una llamada). |
| 2026-06-18 | Flop dividido: se eliminó la consulta única /v1/gto/flop, sustituida por /v1/gto/flop/tree (obtener árbol) + /v1/gto/flop/node (obtener nodo, gratis), alineados con tree/node del solucionador. |
| 2026-06-17 | Se añadió /v1/gto/flop/projected-range (un contenedor práctico sobre /v1/gto/range: proporciona el punto completo de flop + la línea de acciones, el servidor ensambla automáticamente el árbol de decisiones y devuelve directamente el rango de turn). |
| 2026-06-17 | Formato de mesa / mano unificado: la entrada es una cadena sin separadores; la respuesta board siempre se devuelve como un array. |
| 2026-06-17 | Se añadió la especificación OpenAPI 3.0; se añadieron documentos tutoriales de notación de rangos / conceptos / flujo completo. |
| 2026-06-17 | /v1/gto/solver ahora admite resolución de flop en tiempo real (board=3); bet_sizes.flop puede personalizar los tamaños de apuesta del flop. |
| 2026-06-17 | Corrección: el amount_bb de subida de la consulta de flop era incorrectamente 0 (ahora devuelve el BB absoluto correcto). |
| 2026-06-17 | Se añadió la conversión de rango /v1/gto/range; /flop/tree expone los oop_range / ip_range iniciales; /flop y /solver/node devuelven la estrategia de rango completa cuando no se pasa hole_cards. |
| 2026-06-16 | Se añadió la familia de solucionador en tiempo real para turn / river /v1/gto/solver (cuota de resolución independiente); se añadió el árbol de decisiones del flop /v1/gto/flop/tree. |
| 2026-06-15 | Se eliminó el campo recommendation de todas las respuestas — elige tú mismo las acciones según frequency. |
pokerai.bet · GTO API v1