Instantánea de Cuotas
Obtén una instantánea de las cuotas actuales de las casas de apuestas.
GET /api/v1/oddsCambio en v3.0.0: la respuesta de cuotas ahora incluye un único campo timestamp (entrega / frescura del feed). Los antiguos campos odds_changed_at, last_seen_at y wire_received_at se han eliminado — usa timestamp en su lugar. Ya no existe un campo para indicar cuándo se movió el precio por última vez.
Autenticación
Requiere API key. Disponible para todos los planes.
Las casas de apuestas devueltas en tus resultados dependen de tu plan de suscripción. Los usuarios del plan Free reciben cuotas únicamente de DraftKings y FanDuel. Consulta Acceso a Casas por Plan más abajo.
Parámetros de Consulta
| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
sportsbook | string | permitidas por plan | IDs de casas de apuestas separados por comas (p. ej., draftkings,fanduel). Se aplican los límites del plan. |
sport | string | todos | Filtrar por deporte(s), separados por comas (p. ej., basketball, football). Admite alias de categoría. |
league | string | todas | Filtrar por liga(s), separadas por comas (p. ej., nba, nfl, nhl) |
market | string | todos | Filtrar por tipo(s) de mercado, separados por comas. Admite alias de categoría (main, spread, total, props) o tipos exactos (point_spread, player_points). |
event_id | string | — | Filtrar por ID(s) de evento, separados por comas |
is_live | boolean | — | true = solo en directo, false = solo prepartido, omitir = ambos |
min_odds | number | — | Filtro de cuotas americanas mínimas (p. ej., -110) |
max_odds | number | — | Filtro de cuotas americanas máximas (p. ej., +200) |
group_by | string | — | Agrupar resultados por campo (p. ej., event) |
state | string | — | Código de estado de EE. UU. solo para el destino del enlace; no filtra cuotas ni devuelve precios específicos por estado. Acepta los 50 códigos de estados de EE. UU. y dc; los códigos no vacíos no admitidos (incluido on) devuelven 400 invalid_filter. Cuando se establece, las URLs deep_link incluyen ?state=XX; los valores omitidos o vacíos no generan ?state=, y la redirección aplica entonces su propio valor por defecto pa. Solo afecta a las casas con URLs dependientes del estado (BetMGM, Caesars, BetRivers). |
limit | integer | 50 | Máximo de resultados por página (máx. 200) |
offset | integer | 0 | Desplazamiento de paginación. Debe ser ≤ 500. Los valores superiores a 500 devuelven 400 offset_too_large — usa cursor para una paginación más profunda. Puede producir filas duplicadas cuando los datos en directo se actualizan entre solicitudes. |
cursor | string | — | Cursor opaco de next_cursor en una respuesta anterior. Obligatorio para paginación profunda (más allá del offset 500) y recomendado para cualquier escaneo de varias páginas — estable frente a cambios en datos en directo. Tiene prioridad sobre offset cuando se proporcionan ambos. |
Usa valores separados por comas para filtrar por varias casas de apuestas: sportsbook=draftkings,fanduel,betmgm
Alias de Categoría de Mercado
En lugar de listar tipos de mercado individuales, puedes usar un alias de categoría para coincidir con un grupo de mercados relacionados. Los alias y los tipos exactos pueden mezclarse libremente en una lista separada por comas.
| Alias | Se expande a |
|---|---|
main | moneyline, point_spread, total_points |
spread | point_spread, puck_line, run_line, set_handicap |
total | total_points, total_goals, total_runs, total_games, total_rounds, team_total |
props | Todos los tipos de mercado player_* (coincidencia por prefijo) |
# Obtener todos los mercados "main" (moneyline + spreads + totales)
curl "https://api.sharpapi.io/api/v1/odds?league=nba&market=main" \
-H "X-API-Key: YOUR_API_KEY"
# Mezclar un alias con un tipo exacto
curl "https://api.sharpapi.io/api/v1/odds?league=nfl&market=spread,moneyline" \
-H "X-API-Key: YOUR_API_KEY"
# Todos los mercados de player props
curl "https://api.sharpapi.io/api/v1/odds?league=nba&market=props" \
-H "X-API-Key: YOUR_API_KEY"El alias props utiliza una coincidencia por prefijo, por lo que incluye automáticamente cualquier tipo de mercado que comience con player_ (p. ej., player_points, player_rebounds, player_assists, player_strikeouts, etc.).
Ejemplos de Solicitudes
cURL
curl -X GET "https://api.sharpapi.io/api/v1/odds?league=nba&sportsbook=draftkings&market=moneyline" \
-H "X-API-Key: YOUR_API_KEY"Paginación
Usa paginación basada en cursor para escaneos de varias páginas. El endpoint /odds sirve datos en directo que se refrescan cada ~15 segundos. Con paginación basada en offset, las filas pueden cambiar de posición entre solicitudes, causando duplicados en los límites de página. La paginación basada en cursor ancla cada página al último elemento visto — sin desviaciones.
Cada respuesta incluye tanto next_cursor (estable) como next_offset (legacy) en el objeto pagination. Para escaneos secuenciales de un conjunto de datos completo, usa siempre next_cursor.
# Primera página — no se necesita cursor
curl "https://api.sharpapi.io/api/v1/odds?league=nfl&limit=200" \
-H "X-API-Key: YOUR_API_KEY"
# Páginas siguientes — pasa next_cursor de la respuesta anterior
curl "https://api.sharpapi.io/api/v1/odds?league=nfl&limit=200&cursor=eyJlIjoiMzM0ODMxNTMiLCJiIjoiZHJhZnRraW5ncyIsIm0iOiJtb25leWxpbmUiLCJpIjoiZHJhZnRraW5nc18zMzQ4MzE1M19tb25leWxpbmVfUEhJIn0" \
-H "X-API-Key: YOUR_API_KEY"Orden de los resultados
Los resultados se devuelven en orden cronológico por hora de inicio del evento: primero los eventos que ya están en curso y los que empiezan antes, después los posteriores. Los eventos sin hora de inicio en el feed se ordenan al final.
Por tanto, una sola página es una porción del calendario, no una muestra del conjunto completo de resultados. Una casa de apuestas sin partidos que empiecen dentro del tramo del calendario que esa página cubre no aparecerá en ella, aunque tenga muchas filas coincidentes más tarde ese mismo día: es el comportamiento esperado, no una falta de cobertura. Para comprobar si una casa ofrece un mercado, filtra con ?sportsbook= o acota con ?league= en lugar de leer una primera página sin filtrar.
En una página con filas, eso es lo que indica meta.books: una casa que aparece en in_scope sin entrada en in_page no devolvió filas en esa página, normalmente porque sus partidos quedan fuera del tramo del calendario que esa página cubre y no porque no ofrezca el mercado.
Los cursores son opacos — no los analices ni los construyas. Codifican la posición de ordenación del último elemento de la página actual y solo son válidos para los mismos parámetros de filtro.
?offset=N sigue funcionando para paginación superficial (hasta el offset 500) y es apropiado para solicitudes de una sola página o acceso directo por posición. Más allá de 500, la API devuelve 400 offset_too_large — de lo contrario, el servidor tendría que ordenar el conjunto de resultados filtrado completo en cada página, lo que es mucho más barato evitar que optimizar por solicitud. Usa cursor para cualquier cosa más profunda.
{
"error": {
"code": "offset_too_large",
"message": "offset must be <= 500; use `cursor=` from the previous response for deeper pagination",
"max_offset": 500
}
}Respuesta
Éxito (200)
{
"success": true,
"data": [
{
"id": "draftkings_33483153_moneyline_PHO",
"sportsbook": "draftkings",
"event_id": "33483153",
"sport": "basketball",
"league": "nba",
"home_team": "PHI 76ers",
"away_team": "PHO Suns",
"market_type": "moneyline",
"selection": "PHO Suns",
"selection_type": "away",
"odds_american": -150,
"odds_decimal": 1.667,
"odds_probability": 0.60,
"line": null,
"event_start_time": "2026-01-26T19:00:00Z",
"timestamp": "2026-01-26T02:10:24.125Z",
"is_live": false
},
{
"id": "draftkings_33483153_moneyline_PHI",
"sportsbook": "draftkings",
"event_id": "33483153",
"sport": "basketball",
"league": "nba",
"home_team": "PHI 76ers",
"away_team": "PHO Suns",
"market_type": "moneyline",
"selection": "PHI 76ers",
"selection_type": "home",
"odds_american": 130,
"odds_decimal": 2.30,
"odds_probability": 0.4348,
"line": null,
"event_start_time": "2026-01-26T19:00:00Z",
"timestamp": "2026-01-26T02:10:24.125Z",
"is_live": false
}
],
"meta": {
"count": 2,
"total": 3095,
"books_available": ["draftkings", "fanduel", "betmgm", "caesars", "pinnacle"],
"books_returned": ["draftkings"],
"pagination": {
"limit": 50,
"offset": 0,
"has_more": true,
"next_offset": 50,
"next_cursor": "eyJlIjoiMzM0ODMxNTMiLCJiIjoiZHJhZnRraW5ncyIsIm0iOiJtb25leWxpbmUiLCJpIjoiZHJhZnRraW5nc18zMzQ4MzE1M19tb25leWxpbmVfUEhJIn0"
},
"updated_at": "2026-01-26T02:10:37.846Z",
"filters": {
"league": "nba",
"sportsbook": "draftkings",
"market": "moneyline"
}
}
}Resultados vacíos (200): meta.store
Una página vacía —200 con "data": [] y "count": 0— puede significar dos cosas distintas: que tus filtros no coincidieron con nada, o que la instancia que respondió no tenía nada cargado en ese momento (por ejemplo, durante un cambio de store). Desde septiembre de 2026 la respuesta indica cuál de las dos es. Siempre que /odds devuelve cero filas añade un bloque meta.store, y reason es el campo sobre el que debes decidir:
{
"data": [],
"pagination": {
"limit": 50,
"offset": 0,
"count": 0,
"has_more": false,
"next_offset": null
},
"updated_at": "2026-09-07T02:41:18.552Z",
"meta": {
"store": {
"generation": 5019,
"ready": true,
"books": 39,
"rows": 810137,
"reason": "no_match"
}
}
}reason | Significado | Qué hacer |
|---|---|---|
warming | La instancia que respondió no ha completado ningún ciclo de actualización desde su último cambio de modo: todavía no hay nada cargado | Reintentar |
store_empty | La instancia está lista pero no contiene ninguna fila de cuotas, por ejemplo en mitad de un cambio de store | Reintentar; no trates la página vacía como definitiva |
no_match | La instancia está lista y con datos; tus filtros no coincidieron con nada | Definitivo: reintentar no cambiará la respuesta |
| Campo | Tipo | Significado |
|---|---|---|
generation | integer | Generación del snapshot desde la que se sirvió esta respuesta. 0 significa que no se ha cargado nada desde el arranque del proceso. |
ready | boolean | Se ha completado al menos un ciclo de actualización desde el último cambio de modo de la instancia. |
books | integer | Casas de apuestas presentes en el snapshot desde el que se sirvió esta respuesta, independientemente de tus filtros. |
rows | integer | Filas de cuotas contenidas en ese snapshot, independientemente de tus filtros. |
reason | string | warming, store_empty o no_match; ver arriba. |
event_status | string | Presente solo cuando la página está vacía porque el único evento por el que filtraste con event_id ha terminado: final (se conserva un resultado finalizado; el mismo registro que /events/{eventId} sirve como status: "final") o gone (el evento salió del calendario en aproximadamente la última hora sin un resultado finalizado; la misma condición bajo la que /events/{eventId} responde 410 Gone). Omitido en cualquier otro caso. Ver Eventos finalizados más abajo. |
completed_at | string | Acompaña únicamente a event_status: "final": el instante RFC 3339 en que se detectó la finalización, idéntico al completed_at de /events/{eventId}. Nunca se envía con gone. |
- Solo está presente en resultados vacíos. Una respuesta con filas es idéntica byte a byte a la anterior y no incluye
meta.store; los parsers que leendata+pagination+updated_atsiguen funcionando. booksyrowsdescriben el snapshot completo, no tu consulta:rows: 810137demuestra que el store tenía datos, no cuenta lo que habrías obtenido.- Las consultas que se resuelven a dos o más casas de apuestas también incluyen
meta.books(el conjunto de casas resuelto:in_scopey los recuentosin_pagepor casa);meta.storese añade junto a él. Lo mismo ocurre con la página vacía de una selección de casas del dashboard que no se resolvió a ninguna casa; ver Selección de casas vacía más abajo. - Un valor desconocido de
leagueosportsbookse rechaza con400 invalid_filteren lugar de responderse con una página vacía. Los demás filtros no se validan contra el catálogo: unmarket_typeo unevent_idque no existe en ningún sitio devuelve una página vacía normal conreason: "no_match".
Eventos finalizados: event_status y completed_at
Un cliente que sigue consultando /odds?event_id=<id> después de que el partido termine recibe una página vacía definitiva: reason: "no_match" es cierto, pero no dice por qué nada coincidió. Cuando la página está vacía porque el único evento por el que filtraste ha terminado, meta.store también lo indica. Esta es la respuesta real para un partido de la MLB que había terminado esa misma noche (una consulta de una sola casa, para que el cuerpo sea corto; una consulta de varias casas incluye además meta.books, como arriba):
GET /api/v1/odds?event_id=mlb_twins_whitesox_2026-09-06_b3&sportsbook=pinnacle&limit=1{
"data": [],
"pagination": {
"limit": 1,
"offset": 0,
"count": 0,
"has_more": false,
"next_offset": null
},
"updated_at": "2026-09-07T10:04:34.951684418Z",
"meta": {
"store": {
"generation": 13456,
"ready": true,
"books": 39,
"rows": 947879,
"reason": "no_match",
"event_status": "final",
"completed_at": "2026-09-07T02:09:37Z"
}
}
}/events/mlb_twins_whitesox_2026-09-06_b3 devolvió en ese mismo instante status: "final" con el mismo completed_at: ambos endpoints leen el mismo registro, así que no pueden discrepar.
event_status | Significado | Qué hacer |
|---|---|---|
final | Se conserva un resultado finalizado para el evento; completed_at es el momento en que se detectó. | Deja de consultar: el evento ha terminado; obtén el resultado en /events/{eventId} |
gone | El evento salió del calendario en aproximadamente la última hora sin un resultado finalizado: aplazado, cancelado o terminado tan recientemente que aún no se ha registrado ningún resultado. Es la misma condición bajo la que /events/{eventId} responde 410 Gone, y no afirma que el evento haya terminado. | Deja de consultar las cuotas; comprueba /events/{eventId} más tarde para ver si hay resultado |
La señal solo se añade cuando se cumplen todas las condiciones siguientes; en caso contrario el bloque conserva su forma habitual y ninguna de las dos claves está presente:
- la petición filtró por exactamente un
event_id(una lista separada por comas no recibe señal; el campo es singular); - la página está vacía con
reason: "no_match"(una páginawarmingostore_emptynunca la incluye: el vacío es del store, yreasonya indica que reintentes); - se sabe que el evento ha terminado. Un evento todavía en vivo o próximo, o un id que no existe en ningún sitio, recibe un
no_matchnormal sinevent_status; así que una consulta de un solo id respondida sin él significa un id incorrecto o un evento que no ha terminado.
Un evento finalizado cuyas cuotas siguen en caché devuelve esas filas con normalidad; la señal aparece cuando la página se vacía. completed_at es el momento en que se detectó la finalización —normalmente unos minutos después de que el evento saliera del feed en vivo—, no el pitido final; la misma salvedad que completed_at en /events. El código de estado nunca cambia: un cliente que consulta un evento durante toda su vida sigue recibiendo 200.
Selección de casas vacía: meta.books.reason
Si la selección de casas de apuestas guardada en tu dashboard no se resuelve a nada —todas las casas seleccionadas están ausentes del snapshot actual o no están incluidas en tu plan—, una petición a /odds sin filtros se responde con una página vacía. El store está bien; la selección es el motivo, y la respuesta lo nombra. meta.books —normalmente presente solo en consultas que se resuelven a dos o más casas— se emite con un conjunto vacío, reason: "selection_disjoint" y selected, la selección que no se resolvió a nada (IDs canónicos de casa, ordenados):
{
"data": [],
"pagination": {
"limit": 50,
"offset": 0,
"count": 0,
"has_more": false,
"next_offset": null
},
"updated_at": "2026-09-07T10:04:34.951684418Z",
"meta": {
"books": {
"in_scope": [],
"in_page": {},
"reason": "selection_disjoint",
"selected": ["betano", "bwin"]
},
"store": {
"generation": 13454,
"ready": true,
"books": 39,
"rows": 947919,
"reason": "no_match"
}
}
}meta.books.reasontiene prioridad.meta.storesigue apareciendo junto a él conreason: "no_match": correcto para el store (tiene datos), pero no es la causa. Cuandometa.books.reasonestá presente, ese es el motivo de la página vacía; reintentar no cambiará la respuesta. Corrige la selección en tu dashboard, o mejora tu plan si las casas que seleccionaste requieren uno superior.in_scopeein_pageestán presentes y vacíos ([]/{}, nuncanull). El único valor dereasonhoy esselection_disjoint.- Se emite solo cuando la selección es realmente la causa: la petición no llevaba un filtro
sportsbook=explícito, tienes una selección en el dashboard y tu plan por sí solo se habría resuelto al menos a una casa. Nunca aparece en el plan Free (que siempre sirve DraftKings y FanDuel, sea cual sea la selección) ni con un store vacío o en calentamiento: esas páginas las explicameta.store. - Con un filtro
sportsbook=explícito, la misma discrepancia se rechaza en lugar de responderse con una página vacía:403 tier_restricted,403 book_not_selectedo503 book_unavailable. - Las páginas que se resuelven a una o más casas no cambian: el bloque de dos o más casas no lleva
reasonniselected, y un conjunto de una sola casa no llevameta.booksen absoluto.
Cabeceras de Respuesta
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 299
X-RateLimit-Reset: 1737853200
X-Data-Delay: 0
X-Request-Id: req_abc123def456| Cabecera | Descripción |
|---|---|
X-RateLimit-Limit | Máximo de solicitudes por minuto para tu plan |
X-RateLimit-Remaining | Solicitudes restantes en la ventana actual |
X-RateLimit-Reset | Marca de tiempo Unix cuando se restablece el límite de tasa |
X-Data-Delay | Retraso de datos en segundos (0 para tiempo real, 60 para el plan Free) |
X-Request-Id | Identificador único de solicitud para depuración |
Respuestas de Error
401 No Autorizado
Si no se envía ninguna clave se devuelve missing_api_key; una clave inválida devuelve invalid_api_key.
{
"error": {
"code": "missing_api_key",
"message": "API key required. Pass via X-API-Key header, api_key query parameter, or Bearer token.",
"docs": "https://docs.sharpapi.io/en/authentication"
}
}403 Plan Restringido
{
"error": {
"code": "tier_restricted",
"message": "Sportsbook 'pinnacle' requires Sharp tier or higher",
"docs": "https://docs.sharpapi.io/en/pricing"
}
}429 Límite de Tasa Superado
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Retry after 45 seconds.",
"docs": "https://docs.sharpapi.io/en/authentication#rate-limits"
}
}Esquema del Objeto Odds
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador único de la cuota |
sportsbook | string | ID de la casa de apuestas (p. ej., draftkings) |
event_id | string | Identificador del evento |
sport | string | Slug del deporte (p. ej., basketball, football) |
league | string | Slug de la liga (p. ej., nba, nfl) |
home_team | string | Nombre del equipo local |
away_team | string | Nombre del equipo visitante |
market_type | string | moneyline, spread, total, player_prop, etc. |
selection | string | La selección (nombre del equipo, Over/Under, nombre del jugador) |
selection_type | string | Identificador canónico del lado. Consulta Tipos de selección más abajo para el enum completo, incluyendo formas compuestas (p. ej. home_over) que se emiten en mercados multieje. |
team_side | string|undefined | Pista de lado del equipo en bruto desde el adaptador — uno de home, away, draw. Útil cuando selection_type lleva un valor compuesto (p. ej. home_over) y solo necesitas el eje de equipo sin tener que parsear. Ausente cuando el adaptador no lo selló. |
odds_american | number | Cuotas americanas (p. ej., -110, +150) |
odds_decimal | number | Cuotas decimales (p. ej., 1.909) |
odds_probability | number | Probabilidad implícita (p. ej., 0.5238) |
line | number | null | Valor de la línea de spread o total (null para moneyline) |
is_alternate_line | boolean|undefined | true cuando el line de esta fila difiere de la línea principal orientativa de su cohorte — la cohorte es (event, market_type, eje de selección), resuelta por casa de apuestas. Siempre false para mercados sin línea (moneyline, outright). Estable en /opportunities/ev hoy; en despliegue progresivo a las filas de /odds. Úsalo para separar instantáneas de línea principal y líneas alternativas. |
event_start_time | string | Hora de inicio del evento en ISO 8601 |
timestamp | string | Hora ISO 8601 en que SharpAPI refrescó por última vez esta cuota a través de su pipeline — avanza en cada ciclo de ingesta. Es una señal de frescura del feed / actividad; NO es cuándo cambió el precio por última vez. |
is_live | boolean | Si el evento está actualmente en directo |
event_uuid | string|undefined | UUID canónico estable del evento desde el atlas de SharpAPI, cuando el evento está mapeado. Mientras event_id lleva el identificador principal del adaptador (a menudo el de la casa de apuestas originadora), event_uuid es un hash estable entre feeds que puedes usar para joins entre feeds. Ausente para eventos no mapeados. |
external_event_id | string|undefined | El ID de evento nativo de la propia casa de apuestas, cuando difiere de event_id. Útil para enlazar filas de vuelta a la UI o API de la casa de apuestas. |
deep_link | string|undefined | URL resolutiva que apunta a la página de evento o del cupón de la casa de apuestas. Pasa state= (p. ej. state=nj) en la solicitud para enrutar a subdominios específicos por estado en las casas que los requieren (BetMGM, Caesars, BetRivers). |
market_id | string|undefined | Identificador de mercado nativo de la casa de apuestas. Algunas casas no lo exponen — ausente cuando no se conoce. |
selection_id | string|undefined | Identificador de selección/resultado nativo de la casa de apuestas. Algunas casas no lo exponen — ausente cuando no se conoce. |
player_name | string|undefined | Nombre del jugador (solo mercados de player props) |
stat_category | string|undefined | Categoría estadística, p. ej. points, rebounds (solo mercados de player props) |
home_pitcher | string|undefined | Solo MLB. Pitcher abridor del equipo local cuando lo publica la casa de apuestas. |
away_pitcher | string|undefined | Solo MLB. Pitcher abridor del equipo visitante cuando lo publica la casa de apuestas. |
max_bet | number|undefined | El mayor tamaño disponible en esta fila. En un corredor tradicional (Pinnacle, Circa Sports, SBOBET) es la apuesta máxima que aceptará, en USD. En un corredor basado en intercambio es el dinero que está al mejor precio, en size_currency. La ausencia significa que el operador no publica ningún tamaño para la fila; un número — incluido 0.0 — es una cifra real. En un corredor basado en intercambio este campo aparece solo mientras hay dinero al mejor precio, así que un best_bid_liquidity de 0.0 llega sin max_bet — el mismo hecho, no uno contradictorio. Consulta Liquidez y límites. |
size_currency | string|undefined | Código ISO-4217 en el que están denominadas las cifras monetarias de esta fila: max_bet, best_bid_liquidity y total_liquidity. GBP en Betfair y Smarkets, USD en cualquier otro corredor que publique un tamaño, y nunca convertido: la cifra propia del operador se entrega en su propia moneda. Ausente en filas sin tamaño y en corredores tradicionales, cuyo max_bet es un techo de apuesta en USD y no un tamaño en el libro. Consulta Liquidez y límites. |
best_bid_liquidity | number|undefined | Solo corredores basados en intercambio. Dinero que está al precio publicado — lo que un tomador puede emparejar sin mover el precio. Denominado en size_currency. 0.0 significa que no hay nada ahí; la ausencia significa que el operador no publica la cifra. |
total_liquidity | number|undefined | Solo corredores basados en intercambio. Tamaño arriesgable sumado en todo el libro para esta selección, no solo al mejor precio. Denominado en size_currency. 0.0 significa un libro vacío; la ausencia significa que el operador no publica la cifra. No derivable de best_bid_liquidity, y algunos corredores publican uno sin el otro. |
volume | number|undefined | Volumen negociado acumulado en esta selección, en las unidades nativas de la casa de intercambio. Solo casas de intercambio — actualmente Kalshi. Consulta Liquidez y límites. |
volume_24h | number|undefined | Volumen negociado de las últimas 24 horas, en las unidades nativas de la casa de intercambio. Solo casas de intercambio — actualmente Polymarket y Kalshi. |
open_interest | number|undefined | Contratos abiertos pendientes sobre esta selección. Solo casas de intercambio — actualmente Kalshi. |
polymarket_resolution | string|undefined | Solo Polymarket. Estado de resolución del oráculo optimista UMA cuando el mercado ha terminado — uno de settled_normal, voided, disputed, proposed, unknown. Ausente en mercados Polymarket aún en vivo y en todas las casas no-Polymarket. |
Tipos de selección
selection_type lleva el identificador canónico de lado para cada selection. La mayoría de mercados son a dos vías (p. ej. moneyline, point spread, total) y emiten uno de los valores simples siguientes. Un pequeño conjunto de mercados multieje (doble oportunidad de fútbol, BTTS combinado, resultado × O/U, round betting de MMA, set betting de tenis, marcador exacto, etc.) codifica dos resultados por selección y emite valores compuestos unidos por _.
| Familia | Valores | Dónde aparecen |
|---|---|---|
| Dos vías (lado del equipo) | home, away | moneyline, point_spread, puck_line, run_line, set_handicap, la mayoría de mercados por período |
| Dos vías (dirección de línea) | over, under | total_points, total_goals, total_runs, total_games, total_rounds, todos los props player_*_o_u |
| Dos vías (sí/no) | yes, no | binary, mercados de tipo prop sí/no, resultados de intercambio “back/lay”, mercados de predicción de Polymarket |
| Dos vías (paridad) | even, odd | Mercados de paridad de totales (p. ej. total de puntos par/impar) |
| Tres vías | draw | Moneyline a tres vías (1X2 de fútbol), lado complementario del draw-no-bet, “sin gol” en next_goal |
| Compuesto (equipo × O/U) | home_over, home_under, away_over, away_under | match_result_total_goals de fútbol (“Equipo A y Over N.5”) y mercados análogos resultado-más-total. También team_total (“Equipo A Over N.5”), que lleva un equipo y una dirección, por lo que nunca es un home/over simple. |
| Compuesto (equipo × BTTS) | home_yes, home_no, away_yes, away_no, draw_yes, draw_no | match_result_both_teams_to_score de fútbol |
| Compuesto (doble oportunidad) | home_draw, away_draw, home_away | double_chance de fútbol (1X / X2 / 12) y doble oportunidad de MMA |
| Compuesto (round / método) | home_r1, home_r2, home_decision, away_r1, etc. | round_betting de MMA y mercados de método de victoria |
| Comodín | other | game_prop, “sin gol” en next_goal, y cualquier selección donde el mapeador de lado canónico no pueda descomponer el resultado limpiamente. Siempre presente en volumen bajo; trátalo como opaco. |
Parseo de valores compuestos. Las cadenas compuestas de selection_type siempre unen el eje del equipo (home / away / draw) al eje secundario con un único guion bajo. Para recuperar solo el eje del equipo sin parsear, lee team_side — es el lado en bruto sellado por el adaptador para la misma fila.
Los mercados de cola larga emiten formas adicionales. Mercados como correct_score (p. ej. "2_1"), set_betting (p. ej. "0_2"), winning_margin, halftime_fulltime, first_goal y anytime_goal codifican resultados a nivel de marcador o compuestos directamente en selection_type. Si dependes de un enum cerrado, filtra a las familias de arriba y trata cualquier valor no reconocido como opaco — no lances error.
Filtrado por Rango de Cuotas
Usa min_odds y max_odds para filtrar por valor de cuotas americanas.
# Devolver solo cuotas en positivo (+100 y superiores)
curl "https://api.sharpapi.io/api/v1/odds?league=nba&min_odds=100" \
-H "X-API-Key: YOUR_API_KEY"
# Devolver solo cuotas entre -200 y +200
curl "https://api.sharpapi.io/api/v1/odds?league=nba&min_odds=-200&max_odds=200" \
-H "X-API-Key: YOUR_API_KEY"Respuesta Agrupada por Evento
Usa group_by=event para agrupar las cuotas por evento en lugar de una lista plana. Esto es útil para construir interfaces centradas en eventos.
curl "https://api.sharpapi.io/api/v1/odds?league=nba&group_by=event" \
-H "X-API-Key: YOUR_API_KEY"{
"data": [
{
"event_id": "33483153",
"event_name": "PHI 76ers vs PHO Suns",
"sport": "basketball",
"league": "nba",
"start_time": "2026-01-26T19:00:00Z",
"is_live": false,
"odds": [
{
"id": "draftkings_33483153_moneyline_PHO",
"sportsbook": "draftkings",
"market_type": "moneyline",
"selection": "PHO Suns",
"selection_type": "away",
"odds_american": -150,
"odds_decimal": 1.667,
"odds_probability": 0.60,
"line": null,
"timestamp": "2026-01-26T02:10:24.125Z"
}
]
}
],
"meta": {
"group_by": "event",
"books_available": 5,
"filters": { "league": "nba" },
"updated_at": "2026-01-26T02:10:37.846Z"
}
}Acceso a Casas por Plan
Las casas de apuestas incluidas en tus resultados de cuotas dependen de tu plan de suscripción:
| Plan | Casas Disponibles | Casas de Apuestas Incluidas |
|---|---|---|
| Free | 2 | DraftKings, FanDuel |
| Hobby | 5 | + BetMGM, Caesars, theScore Bet |
| Pro | 15 | + Bet365, BetRivers, y más |
| Sharp | 25 (de 43) | 25 casas a tu elección de las 43 |
| Enterprise | Todas | Todas las casas de apuestas disponibles |
Pinnacle (sharp book) requiere el plan Sharp o superior. Solicitar sportsbook=pinnacle en un plan Free, Hobby o Pro devolverá un error 403 tier_restricted.
Ejemplos de Filtrado
# Obtener cuotas en directo de la NBA de todas tus casas disponibles
curl "https://api.sharpapi.io/api/v1/odds?league=nba&is_live=true" \
-H "X-API-Key: YOUR_API_KEY"
# Obtener cuotas moneyline y spread para un evento específico
curl "https://api.sharpapi.io/api/v1/odds?event_id=nba_76ers_suns_2026-01-26_b3&market=moneyline,spread" \
-H "X-API-Key: YOUR_API_KEY"
# Paginar por todas las cuotas de spread de la NFL (usa next_cursor de cada respuesta)
curl "https://api.sharpapi.io/api/v1/odds?league=nfl&market=spread&limit=200" \
-H "X-API-Key: YOUR_API_KEY"Endpoints Relacionados
- Odds Delta - Obtén solo las cuotas que cambiaron desde una marca de tiempo dada
- Best Odds - Obtén las mejores cuotas de todas las casas para cada selección
- Odds Comparison - Compara cuotas entre casas lado a lado
- Batch Odds - Obtén cuotas para varios eventos en una sola solicitud
- Markets - Lista los tipos de mercado disponibles
- Sportsbooks - Lista las casas de apuestas disponibles y su estado