Estado de Juego en Vivo
Estado de juego en vivo agregado — marcadores, periodos, relojes, posesión y datos situacionales específicos de cada deporte — fusionado entre sportsbooks en una única vista autorizada por evento. Una fila por encuentro en vivo, seleccionada por consenso entre los libros que lo cubren.
GET /api/v1/gamestate
GET /api/v1/gamestate/{sport}Autenticación
Requiere API key. Disponible con el complemento Game State ($79/mes) o el
plan Enterprise. Las claves sin ninguno de los dos reciben 403 tier_restricted
con addon: "game_state" en el cuerpo del error. Añade el complemento desde la
página de facturación en cualquier plan de pago
(Hobby / Pro / Sharp); las claves Enterprise lo tienen incluido.
El estado de juego en vivo también se transmite a través del canal gamestate en
SSE y WebSocket
— consulta Streaming más abajo. (El acceso al streaming requiere el
complemento WebSocket o Enterprise, además del requisito de Game State
indicado anteriormente.)
Parámetros de Ruta
| Parámetro | Tipo | Descripción |
|---|---|---|
sport | string | (opcional) Un único deporte a devolver. Coincide con un deporte conocido del Atlas (baseball, basketball, football, hockey, soccer, tennis, table_tennis, cricket, esports, snooker, other). Sin distinción entre mayúsculas y minúsculas. Los deportes desconocidos devuelven un objeto data vacío. |
Sin el parámetro de ruta, devuelve todos los deportes con eventos en vivo.
Sobre de Respuesta
{
"data": {
"<sport>": {
"<event_id>": { ...event state... }
}
},
"updated_at": "2026-04-23T23:55:01.234Z"
}Cada estado de evento se indexa por su event_id canónico dentro del
contenedor de su deporte. updated_at es la hora del servidor en la que se
construyó esta respuesta — úsala para evaluar la frescura si haces polling.
Campos del Estado del Evento
Todos los campos son opcionales excepto donde se indique. La presencia varía
según el deporte — los eventos de tenis incluyen sets_home / server; los eventos
de hockey incluyen power_play; los eventos de fútbol incluyen corners_* /
yellow_cards_*; etc.
Siempre presentes
| Campo | Tipo | Notas |
|---|---|---|
home_team | string | Nombre normalizado del equipo local |
away_team | string | Nombre normalizado del equipo visitante |
sport | string | Contenedor del deporte (baseball, soccer, …) |
league | string | Identificador de liga del Atlas (p. ej. mlb, england_-_premier_league) |
home_score | integer | Puntuación actual del local en la unidad natural del deporte (carreras, puntos, goles, sets — el tenis usa la suma de puntos por set) |
away_score | integer | Puntuación actual del visitante |
is_live | boolean | Siempre true en este endpoint (los eventos no en vivo no se incluyen) |
primary_book | string | El libro del que se seleccionaron las puntuaciones fusionadas. Respeta el consenso — los libros de mayor calidad ganan los empates |
book_count | integer | Número de sportsbooks que aportaron estado en vivo para este evento en el momento de la fusión |
Temporales (la mayoría de deportes de equipo)
| Campo | Tipo | Ejemplo |
|---|---|---|
game_period | string | "T5" (parte alta de la 5.ª entrada de MLB), "Q3" (Q3 de NBA), "2H" (2.ª parte de fútbol), "P2" (NHL), "S2" (2.º set de tenis), "FT" (tiempo completo) |
game_clock | string | "49:06" para deportes con cronómetro ascendente (fútbol), "5:42" para deportes con cuenta atrás (baloncesto, hockey) |
Situacionales
| Campo | Tipo | Notas |
|---|---|---|
possession | "home" | "away" | Qué equipo tiene la posesión (deportes de equipo) o está sirviendo (tenis) |
server | "home" | "away" | Solo tenis — sacador actual |
last_play | string | Descripción de la última jugada específica del deporte cuando esté disponible |
is_timeout | boolean | true durante un tiempo muerto |
Específicos por deporte
| Campo | Deporte | Tipo |
|---|---|---|
fouls_home, fouls_away | baloncesto, fútbol | integer |
corners_home, corners_away | fútbol | integer |
yellow_cards_home, yellow_cards_away | fútbol | integer |
red_cards_home, red_cards_away | fútbol | integer |
power_play | hockey | "home" | "away" |
sets_home, sets_away | tenis | integer (sets ganados) |
hits_home, hits_away | béisbol | integer |
home_pitcher, away_pitcher | béisbol | string — nombre visible del pitcher inicial |
wickets_home, wickets_away | cricket | integer |
overs | cricket | float |
batting_team | cricket | "home" | "away" |
Frescura
| Campo | Tipo | Significado |
|---|---|---|
stale | true (omitido en caso contrario) | El TTL de la clave de livestate del primary_book cayó por debajo del umbral de frescura del agregador (~10s) en el momento de la fusión. Las puntuaciones son los últimos valores conocidos; el libro ha quedado en silencio. Considera que las puntuaciones y el periodo del evento podrían ir retrasados respecto al estado real del partido. |
aggregator_stale | true (omitido en caso contrario) | El propio agregador de SharpAPI no ha escrito un nuevo shard gamestate:{sport} para este deporte en más de ~30s. Señal más amplia que stale — indica un problema en el pipeline, no de un único libro. Si lo observas de forma persistente, contacta con soporte. |
Ausencia = fresco. Tanto stale como aggregator_stale solo se
escriben cuando son verdaderos, manteniendo el payload compacto. Si no los
ves en un evento, los datos se consideran frescos.
Ejemplos de Solicitudes
cURL
# Todos los eventos en vivo de cada deporte
curl "https://api.sharpapi.io/api/v1/gamestate" \
-H "X-API-Key: YOUR_API_KEY"
# Un solo deporte
curl "https://api.sharpapi.io/api/v1/gamestate/soccer" \
-H "X-API-Key: YOUR_API_KEY"Ejemplo de Respuesta
{
"data": {
"soccer": {
"argentina_-_primera_division_bocajuniors_defensayjusticia_2026-04-23": {
"home_team": "Defensa y Justicia",
"away_team": "Boca Juniors",
"sport": "soccer",
"league": "argentina_-_primera_division",
"home_score": 0,
"away_score": 1,
"game_period": "2H",
"game_clock": "49:06",
"is_live": true,
"possession": "away",
"corners_home": 1,
"corners_away": 0,
"fouls_home": 0,
"fouls_away": 0,
"yellow_cards_home": 0,
"yellow_cards_away": 0,
"red_cards_home": 0,
"red_cards_away": 0,
"primary_book": "draftkings",
"book_count": 6
},
"chile_-_primera_division_concepcion_palestino_2026-04-24": {
"home_team": "Palestino",
"away_team": "Concepción",
"sport": "soccer",
"league": "chile_-_primera_division",
"home_score": 0,
"away_score": 0,
"is_live": true,
"primary_book": "unibet",
"book_count": 1,
"stale": true
}
}
},
"updated_at": "2026-04-23T23:55:01.234Z"
}Modelo de Fusión Entre Libros
Los campos de cada evento se fusionan a partir del snapshot de livestate de cada sportsbook mediante un algoritmo de tres clases:
- Clase A — Puntuaciones se eligen por consenso: entre los libros con el rango de periodo más avanzado, gana la puntuación total más alta con ≥2 respaldos. Una puntuación atípica reportada por un único libro (común en los primeros segundos de un cambio de marcador, o por un adaptador con mal comportamiento) se rechaza.
- Clase B — Campos temporales (
game_period,game_clock) se seleccionan según la dirección del reloj específica del deporte — cuenta atrás frente a cuenta ascendente — y el rango del periodo. - Clase C — Campos situacionales (
possession,corners_*, etc.) se rellenan por prioridad a partir de una clasificación fija de libros.
primary_book indica de qué libro provienen las puntuaciones ganadoras.
book_count es el número total de libros que aportaron cualquier estado
para el evento en el momento de la fusión.
Streaming
Cada actualización que el endpoint REST mostraría en el siguiente poll
también dispara un evento gamestate:update en los canales de streaming:
- SSE:
GET /api/v1/stream/gamestate - WebSocket: suscríbete a
{channels: ["gamestate"]}enwss://ws.sharpapi.io/ws
Los clientes de streaming reciben un gamestate:snapshot inicial con el
estado actual completo (una lista plana de filas de eventos), después
eventos gamestate:update que llevan las filas modificadas conforme se
fusionan, y eventos gamestate:removed cuando los eventos salen del
conjunto en vivo.
Rate Limits y Cuotas
Los rate limits siguen tu plan base, no el complemento — las claves Hobby
mantienen sus 120 req/min, Pro mantiene 300, Sharp mantiene 1.000, Enterprise
personalizado. Consulta Precios . /gamestate
cuenta igual que otras llamadas REST en la cuota por minuto.
Resolución de Problemas
- 403
tier_restrictedconaddon: "game_state"— tu clave no tiene el complemento Game State. Añádelo desde Facturación por $79/mes, o actualiza a Enterprise. - Objeto
datavacío — no hay eventos en vivo en el ámbito. Esto es habitual entre eventos de calendarios deportivos más pequeños. Vuelve a hacer polling. - Eventos con
stale: true— el libro principal ha quedado en silencio. Las puntuaciones pueden ir con retraso; considera filtrarlos o mostrar un indicador en la interfaz. - Eventos con
aggregator_stale: true— el agregador de SharpAPI no ha refrescado ese deporte en >30s. Si es persistente, contacta con soporte; un breve aumento puede ocurrir durante los redespliegues. - El mismo partido aparece dos veces bajo
event_ids diferentes — limitación conocida en algunas ligas regionales donde los sportsbooks usan nomenclatura de liga inconsistente. Usa(home_team, away_team)como clave secundaria de deduplicación en el cliente hasta que se cierren los huecos de alias restantes.