Documentación
API operativa
Documentación/Descripción general
Una clave · cuatro calles

Obtén una estrategia en una solicitud.

Usa 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.

Colección de Postman

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.

Elige tu ruta

Ambas usan la misma clave de API y cuota mensual.

Consulta prerresuelta

RÁPIDO

Soluciones de preflop y más de 5.8M soluciones de flop. Devuelve una estrategia en milisegundos sin sondeo de tareas.

Empieza con preflop

Resolución en tiempo real

PERSONALIZADO

Á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ón

Primera respuesta 200

Instala, autentícate y llama. No hay nada más que aprovisionar.

01 / InstalarElige un SDK
02 / AutenticarseExporta una clave
03 / SolicitudLlama a preflop
request.sh
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}]}'
response.json41ms · 200 OK
{
  "hole_cards": "AhKh",
  "situation": "RFI",
  "strategy": [
    { "action": "raise", "frequency": 1, "amount_bb": 3, "sizing_pot": 0.8 }
  ],
  "quota": { "used": 6, "limit": 100 }
}

Continúa creando

Pasa de la primera llamada a producción sin tener que buscar en una única página larga.

Autenticación

Cada solicitud debe incluir una clave API. Obtén una clave en 60 segundos:

  1. Abre la consola, introduce tu correo electrónico → recibe un código de verificación por correo (inicio de sesión sin contraseña, no es necesario registrarse).
  2. Introduce el código para iniciar sesión → crea una clave API → cópiala (solo se muestra una vez, guárdala de forma segura).
  3. Configúrala como variable de entorno: 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

Cuota

Dos tipos de cuota mensual, medidos por separado y restablecidos el día 1 de cada mes; el uso actual está en la consola:

  • Cuota general (predeterminado gratuito: 1.000/mes): preflop, rango preflop, obtención del árbol de decisiones de flop, conversión de rangos /v1/gto/range, y llamadas de rango proyectado consumen 1 cada una.
  • Cuota de resolución (predeterminado gratuito: 25/mes): el solver en tiempo real /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).

Modelo de errores

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:

HTTPerror / significado¿reintentar?
400Entrada no válida o campo ausente (consulta la tabla de cada endpoint para el error específico).No, corrige la entrada
401missing_api_key / invalid_api_key: clave ausente o no válida.No, comprueba la clave
403invalid_node_token / invalid_solve: token/identificador no válido o no te pertenece.No, vuelve a obtener el árbol / reprograma primero
404no_solution: todavía no hay datos GTO para esta situación.No, cambia la situación
429quota_exceeded (general) / solve_quota_exceeded (solve): cuota mensual agotada.No, se restablece el día 1 o mejora tu cuota
429status: busy: todos los solvers están ocupados (solo /v1/gto/solver), sin cargo.Sí, espera y vuelve a intentarlo
502no_result (reason: timeout / no_worker_available) / auth_unavailable / solver_unreachable: backend temporalmente no disponible.Sí, espera y vuelve a intentarlo 2–3 veces

Ejemplos de cuerpos de respuesta de error

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.

Inicio rápido

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.

SDKs de cliente Python · TypeScript · MCP

¿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.

Python pip

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}}

TypeScript / JavaScript npm

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.

MCP (para agentes LLM) npm

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).

Conceptos

El modelo mental general — léelo una vez y las secciones por endpoint de abajo resultarán más sencillas.

Dos formas de obtener una estrategia

  • Soluciones preresueltas: preflop / flop aprovechan soluciones GTO preresueltas, devueltas en milisegundos, adecuadas para casos de uso que necesitan una respuesta rápida.
  • Cálculo del solver en tiempo real: flop / turn / river se calculan en vivo mediante el solver (el flop tarda unos 70 segundos; turn/river son más rápidos), adecuado para cualquier rango/situación personalizado.
  • Conversión de rangos: actualiza un rango a lo largo de una línea de acciones al rango que entra en la siguiente calle y, después, introdúcelo en el solver.

No se devuelve una acción recomendada

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).

Tamaño de apuesta: amount_bb y sizing_pot

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):

  • bet (primera apuesta) = apuesta ÷ bote.
  • raise (ante una apuesta) = (subida hasta − apuesta actual) ÷ bote después del call.

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.

árbol → nodo (obtener árbol → obtener nodo)

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: /flop/tree (cobra 1) → /flop/node (gratis). El nodo root = la primera decisión de Hero.
  • solver: la programación de /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.

Máquina de estados del nodo (resolución en tiempo real)

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.

Soluciones preresueltas preresueltas · milisegundos

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.

Preflop

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…).

Notas · cuerpo de la solicitud

campotipodescripción
hole_cardsstringLas 2 cartas privadas de Hero; por ejemplo, "AdKd".
positions.herostringLa posición de Hero, una de SB BB UTG MP CO BTN (situada dentro de positions).
preflop_actionsarrayLa 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_versionstringOpcional. 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.

Campos de cada elemento de preflop_actions

campotipodescripción
positionstringLa posición de esta acción, una de SB BB UTG MP CO BTN.
actionstring"small blind" / "big blind" / "raise" / "call" / "fold" (ten en cuenta que las ciegas son cadenas de dos palabras).
amountnumberEl 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.
allinbooleanOpcional. 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.

Ejemplo de llamada

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.

Respuesta (200)

{"hole_cards": "AhKh", "situation": "Raise", "strategy": [{"action": "raise", "frequency": 1, "amount_bb": 9, "sizing_pot": 0.8}], "quota": {"used": 7, "limit": 100}}
campodescripción
hole_cardsLa mano repetida en la respuesta.
situationEl 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.
quotaUso 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 Herosituaciónamount_bb
0apertura3
13bet9
24bet25
≥35bet+all-in 100 (allin: true)

Versiones de estrategia preflop_version

El 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_200NL6 max 100bb GG 200NL 3b/f 2.2x - 2.5x
6max_RC_100bb_100NL6 max 100bb GG 100NL 3b/f
6max_RC_40bb6 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"}

Posibles errores

HTTPerrordesencadenante / cómo corregirlo
400invalid_hole_cardshole_cards no son 2 cartas (p. ej., "AdKd").
400unsupported_table_size / invalid_positions / invalid_actionsEl tipo de mesa (actualmente solo 6max), hero/las posiciones o preflop_actions no son válidos.
400unsupported_preflop_versionpreflop_version no está en el conjunto permitido (6max / 6max_RC_100bb_200NL / 6max_RC_100bb_100NL / 6max_RC_40bb).
404no_solutionNo hay una solución prerresuelta para este spot preflop; cambia el spot.

Descargar: request.jsonresponse.json

Rango completo (13×13) consume 1 cuota general

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.

Árbol de decisiones del flop

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 (treenode).

1) Obtener el árbol de decisiones consume 1 cuota general

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.

boardLas 3 cartas del flop, p. ej., "2c2h2s".
pot_type"SRP" con una sola subida / "3BET" / "4BET" / "LIMP" limpeado.
positionsLa posición de cada rol (SB BB UTG MP CO BTN), necesaria por pot_type como se indica a continuación.
flop_versionOpcional. 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_typeposiciones necesariasvalor de Hero
SRPhero, raiser, callersubidor o pagador
3BET / 4BEThero, raiser, three_bettorsubidor o quien hace la tercera apuesta
LIMPhero, limperuno 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}}
campodescripción
oop_range / ip_rangeEl 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_countPozo, stack efectivo (BB) y número total de nodos de decisión.
quotaUso de la cuota general de este mes (used / limit).

2) Obtener la estrategia de un nodo gratis

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}
campodescripción
is_heroSi este nodo es una decisión de Hero.
strategy[]Nodo de Hero (con hole_cards): la estrategia mixta para esta mano. actioncheck / 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_strategyNodo 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).

Posibles errores

HTTPerrordisparador / cómo solucionarlo
4001) invalid_board / invalid_positions; 2) missing_node / invalid_hole_cards1) board no tiene 3 cartas o hero/las posiciones no son válidas; 2) falta node o hole_cards no tiene 2 cartas.
403invalid_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.
404no_solutionNo hay solución preresuelta para este spot/board.

Descargar: tree_request.jsontree_response.jsonnode_request.jsonnode_response.json

Solucionador (en tiempo real) solver

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).

Ejemplo de llamada (tres pasos: 1) programar → 2) sondear el árbol → 3) obtener un nodo)

# 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..."}'

1) Programar una resolución consume 1 resolución

board3=flop / 4=turn / 5=river, p. ej. "2c2h2s9d" (turn).
oop_range / ip_rangeObligatorio. Los rangos de los dos jugadores que entran en esta calle, cadenas de combinaciones ponderadas, p. ej. "AsKs:1,QQ:0.75,...".
pot / effective_stackObligatorio. El bote y el stack efectivo restante (BB) al entrar en esta calle; determinan los tamaños de apuesta y deben ser reales.
heroObligatorio: "OOP" o "IP".
bet_sizesOpcional: 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_sizesOpcional: 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_sizesOpcional: 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_limitOpcional: 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 / casodescripción
solveEl identificador de la resolución, usado por los posteriores /tree y /node; el rango se proporciona solo una vez en este paso.
status = computingSe activó una nueva resolución y consume 1 cuota de resolución (consulta solve_quota).
status = queryableYa existe una resolución en caché para este spot, sin cargo (sin campo solve_quota); consulta /tree directamente.
429 status = busyTodos 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.

2) Obtener el árbol de decisiones + estado del nodo gratis

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…"}, …]}
/ node_count
campodescripción
spot_statusEstado 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_countCalle, 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_secondsTiempo 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.

3) Obtener la estrategia de un nodo gratis

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}]}
campodescripción
is_heroIndica 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_strategyNodo 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/releasereferencia interactiva.

Posibles errores

HTTPerrordesencadenante / cómo corregirlo
400invalid_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.
400missing_solve / missing_node(obtener árbol/nodo) falta el identificador solve o el token node.
403invalid_solve / invalid_node_tokenEl identificador/token no es válido o no es tuyo: vuelve a programar / a obtener el árbol.
429status: busyTodos los solvers están ocupados, sin cargo; espera y vuelve a intentarlo.
502solve_failedNo se pudo activar la resolución; vuelve a intentarlo más tarde.
503upstream_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

Ejemplo de sondeo de extremo a extremo (Python)

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"])

Conversión de rangos rango

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.

Cuerpo de la solicitud

{
  "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.)

Ejemplo de llamada

# 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

Respuesta (200, respuesta real, cadenas largas truncadas)

{"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}}
campodescripción
range_oop_new / range_ip_newEl 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_rawEl 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_normalizationEl 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_ipClasificación de fuerza de mano (combo:rank; un valor menor es más fuerte).
hand_bottom_ranks_oop / hand_bottom_ranks_ipClasificación del extremo inferior del rango.
node_id / board / path_lengthLa 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_ratioLos parámetros de descuento de farol usados realmente esta vez.
quotaUso de la cuota general de este mes (used / limit).

Posibles errores

HTTPerrordesencadenante / cómo corregirlo
400missing_fieldFalta uno de range_oop / range_ip / solver_results / node_id.
400bad_requestEl 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)

Rango proyectado del flop projected-range

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.

Cuerpo de la solicitud

{
  "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"]
}
campodescripción
boardObligatorio. El flop (cadena sin separadores, igual que en otros endpoints), p. ej. "2c2h2s".
pot_typeObligatorio. El tipo de bote, p. ej. "SRP".
positionsObligatorio. { hero, raiser, caller } (igual que en flop); los spots 3bet/limp pueden incluir three_bettor / limper.
node_idOpcional; 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".
normalizeOpcional; el valor predeterminado es true. Indica si se debe normalizar el rango actualizado.
bluff_discount_ratio / bluff_combos_ratioOpcionales, 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_handBloqueo 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_handsArray 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_versionOpcional. 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.

Ejemplo de llamada

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

Respuesta (200, todos los campos enumerados, cadenas largas truncadas)

{"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}}
campodescripción
range_oop_new / range_ip_newEl 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_rawEl 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_normalizationEl 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_ipClasificación de fuerza de mano (combo:rank; un valor menor es más fuerte).
hand_bottom_ranks_oop / hand_bottom_ranks_ipClasificación del extremo inferior del rango.
node_id / board / pot_type / path_lengthLa 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_ratioLos parámetros de descuento de farol usados realmente esta vez.
quotaUso de la cuota general de este mes (used / limit).

Posibles errores

HTTPerrordesencadenante / cómo corregirlo
400invalid_board / invalid_positionsel board no tiene 3 cartas o positions.hero no es válido.
404no_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

Rango proyectado en turn (turn→river) projected-range

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).

Cuerpo de la solicitud

{
  "solve": "eyJ…",
  "node_id": "root/CHECK/BET 6.000000/CALL",
  "normalize": true,
  "bluff_discount_ratio": 0.8,
  "hero_position": "oop",
  "hero_hand": "AsKs"
}
campodescripción
solveObligatorio. El identificador de resolución devuelto por /v1/gto/solver (una resolución de turn).
node_idObligatorio. 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).
normalizeOpcional; el valor predeterminado es true. Indica si se debe normalizar el rango actualizado.
bluff_discount_ratioOpcional. Descuento de faroles (0..1).
hero_position / hero_handBloqueo 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_handsMatriz 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.

Ejemplo de llamada

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

Respuesta (200, todos los campos enumerados, cadenas largas truncadas)

{"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,…"}
campodescripción
range_oop_new / range_ip_newEl 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_normalizationLos 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_lengthLa 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_ratioLos 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).

Posibles errores / estados

HTTPerror / estadodesencadenante / 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.
400missing_solve / missing_node_idFalta el identificador solve o node_id.
410expiredLa resolución caducó (TTL); vuelve a programarla mediante /v1/gto/solver.
502no_solution, etc.Error de resolución del servicio ascendente.

Descargar: request.jsonresponse.json

EV por nodo solver

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.

Cuerpo de la solicitud

{
  "solve": "eyJ0Ijoic2x2X3h4eXoi...(identificador de /v1/gto/solver)",
  "node_id": "root",
  "hand": "2c2d"
}
campodescripción
solveObligatorio. El identificador de resolución de /v1/gto/solver.
node_idObligatorio. Un nodo de /v1/gto/solver/tree (notación del solver; p. ej., "root", "root/CHECK/BET 6.000000").
handOpcional. Filtra a los EV de una mano (p. ej., "2c2d"); omítelo para todas las manos.

Respuesta (200, la matriz de EV de cada mano se alinea con 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": […], …}}
campodescripción
actionsLas acciones del nodo en orden; la matriz de EV de cada mano se alinea con ellas.
evsPor mano → matriz del EV de cada acción (bb). Con hand, evs es una única matriz para esa mano.
player / round / node_id / task_idQué 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).

Jugar una mano (flujo completo)

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).

1) Preflop — ¿debemos abrir?

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.

2) Flop — estrategia de flop

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.

3) Turn — resolución en tiempo real, rango derivado 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:

  1. /v1/gto/flop/tree para los oop_range / ip_range iniciales y los nodos de decisión.
  2. A lo largo de una línea de acción del flop (p. ej., 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.
  3. /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.
  4. Proporciónalos al solver (board con 4 cartas), consulta el árbol hasta que sea 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.

4) River — resolución en tiempo real

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.

API del motor de póker / semántica

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 directoreferencia interactiva; especificación legible por máquina → /openapi.en.json (instantánea combinada de GTO + pokerkit).

Semántica de board / mano consume 1 general

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).

Campos de solicitud (compartidos en este grupo)

campodescripción
boardObligatorio. 3/4/5 cartas comunitarias, sin separadores; p. ej., "AsKsQs".
holeObligatorio 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_typeOpcional; el valor predeterminado es StandardHighHand (solo v1; otros tipos devuelven 400).
deadOpcional. Cartas muertas / retiradas (aceptadas por todos los endpoints de este grupo).

Textura consume 1 general

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}}

Nuts consume 1 general

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"}}}

Combos por categoría consume 1 general

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"]}], …}}}

Informe del board consume 1 general

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"}}}}

Nivel de mano consume 1 general

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"}}}

Proyectos consume 1 general

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"}}}

Outs consume 1 general

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}}

Bloqueadores consume 1 general

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}}

Informe de mano consume 1 general

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}}}

Rangos / equity consume 1 general

/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).

Campos de solicitud (compartidos en este grupo)

campodescripció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.
boardCartas 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.

Expandir rango consume 1 general

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"]]}

Valor del rango consume 1 general

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"], …]}

Ventaja de nuts del rango consume 1 general

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"}}}

Evaluación · equity · ICM · notación

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).

Campos de solicitud (compartidos en este grupo)

Los endpoints de Monte-Carlo (equity / hand-strength / range/equity-advantage) consumen el cupo de solve; el resto consume general.

campodescripción
hole / holdings / boardEntradas de evaluación: un único hole + board (eval/hand), o varios holdings (2+) + board (eval/compare).
ranges / hole_range / hero / villainNotación de rango (equity / hand-strength / range/equity-advantage).
sample_count / seedMonte-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.

Evaluar mano consume 1 general

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"}}}

Comparar evaluación consume 1 general

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"}}]}

Equity consume 1 solve

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}}

Fuerza de la mano consume 1 solve

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}}

ICM consume 1 general

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]}}

Ventaja de equity del rango consume 1 solve

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}}

Analizar notación consume 1 general

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}}

Simulación de juego consume 1 general

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).

Campos de solicitud (compartidos en este grupo)

campodescripción
variantObligatorio. Código de variante, por ejemplo, "NT" (hold'em sin límite); lista completa en /v1/pokerkit/meta.
antes / starting_stacksObligatorio. Antes / stacks iniciales por jugador (matrices de enteros).
blinds_or_straddles / min_betCiegas / straddles; min_bet es obligatorio para no-limit / pot-limit (fixed-limit / stud usan small_bet / big_bet / bring_in).
actionsLista 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).

Estado de las partidas cuesta 1 general

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"]}}

Paso de las partidas cuesta 1 general

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"]}}

Repetición de notación cuesta 1 general

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}}

Normalizar cartas cuesta 1 general

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).

Todas las descargas de ejemplos

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.

Versionado y registro de cambios

Política de versionado

  • El /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.
  • Las adiciones compatibles con versiones anteriores (nuevos endpoints, nuevos campos opcionales, nuevos campos de respuesta) se agregan directamente a /v1 sin aviso por separado — analiza ignorando los «campos desconocidos» y no valides estrictamente mediante una lista permitida los campos de respuesta.
  • El desuso de campos se indicará de antemano en el registro de cambios de abajo, y se eliminarán solo tras un período de transición.

Registro de cambios

fechacambio
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-12Se 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-04Se 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-22Se 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-22Se añadió /v1/gto/preflop/range (todo el rango preflop de 13×13, 169 manos en una llamada).
2026-06-18Flop 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-17Se 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-17Formato de mesa / mano unificado: la entrada es una cadena sin separadores; la respuesta board siempre se devuelve como un array.
2026-06-17Se 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-17Corrección: el amount_bb de subida de la consulta de flop era incorrectamente 0 (ahora devuelve el BB absoluto correcto).
2026-06-17Se 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-16Se 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-15Se eliminó el campo recommendation de todas las respuestas — elige tú mismo las acciones según frequency.

pokerai.bet · GTO API v1