Delta de Cuotas
Obtén solo las cuotas que han cambiado desde una marca de tiempo dada. Este endpoint devuelve el mismo formato de cuotas que /odds pero filtrado a los elementos actualizados después de tu valor since, lo que lo hace ideal para clientes de polling que desean actualizaciones incrementales sin volver a obtener la instantánea completa.
GET /api/v1/odds/deltaAutenticación
Requiere API key. Disponible para todos los planes.
Avanza since desde la página terminal de cada ventana de delta — la página donde pagination.has_more es false. En esa página, meta.server_time informa la marca de agua del servidor; úsala como since de tu siguiente solicitud. En todas las páginas anteriores (has_more: true), meta.server_time se mantiene deliberadamente en el since que enviaste, para que no puedas saltarte filas que aún no has recuperado — interprétalo ahí como «sigue paginando», no como una nueva marca de agua.
Parámetros de Consulta
| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
since | string | obligatorio | Marca de tiempo ISO 8601. Devuelve solo cuotas actualizadas después de este momento (p. ej., 2026-02-11T12:00:00Z) |
sportsbook | string | todos | IDs de casas de apuestas separados por comas (p. ej., draftkings,fanduel) |
sport | string | todos | Filtrar por deporte (p. ej., basketball, football) |
league | string | todas | Filtrar por liga (p. ej., nba, nfl) |
market | string | todos | Filtrar por tipo de mercado (p. ej., moneyline, spread, total). Admite alias de categoría — consulta Cuotas: Alias de Categoría de Mercado. |
event_id | string | - | Filtrar por ID de evento |
is_live | boolean | false | Devolver solo eventos en vivo/in-play |
min_odds | number | - | Filtro de cuotas americanas mínimas (p. ej., -110) |
max_odds | number | - | Filtro de cuotas americanas máximas (p. ej., +200) |
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. 500) |
offset | integer | 0 | Desplazamiento de paginación. Debe ser ≤ 500. Mientras has_more sea true, solicita la página siguiente con offset igual al next_offset de la respuesta, manteniendo since sin cambios. Avanza since solo desde la página terminal (has_more: false). |
El parámetro since es obligatorio. Omitirlo devuelve un error 400 validation_error.
since tiene una ventana de retención de 10 minutos para eliminaciones. Las eliminaciones de cuotas con más de 10 minutos de antigüedad se eliminan de la memoria. Si envías un since anterior a eso, el array data aún respeta tu marca de tiempo, pero la lista removed solo puede contener cuotas eliminadas en los últimos 10 minutos — y se establecerá since_clamped: true en la respuesta. Avanza since con la cadencia indicada en la sección Patrón de Polling más abajo para evitar esto.
Ejemplos de Solicitudes
cURL
# Obtener todos los cambios de cuotas en los últimos 30 segundos
curl -X GET "https://api.sharpapi.io/api/v1/odds/delta?since=2026-02-11T12:00:00Z&league=nba" \
-H "X-API-Key: YOUR_API_KEY"Respuesta
Éxito (200)
{
"data": [
{
"id": "199954867251468",
"sportsbook": "draftkings",
"event_id": "nba_celtics_lakers_2026-02-08_b3",
"sport": "basketball",
"league": "nba",
"home_team": "Los Angeles Lakers",
"away_team": "Boston Celtics",
"market_type": "moneyline",
"selection": "Boston Celtics",
"selection_type": "away",
"odds_american": -150,
"odds_decimal": 1.667,
"odds_probability": 0.60,
"line": null,
"event_start_time": "2026-02-08T19:00:00Z",
"timestamp": "2026-02-08T12:00:15.125Z",
"is_live": false,
"is_main_line": true
}
],
"removed": [
{
"id": "102044417046441",
"sportsbook": "pinnacle",
"removed_at": "2026-02-08T12:00:07Z",
"event_start": "2026-02-08T12:00:00Z",
"was_live": false,
"boundary": true
}
],
"pagination": {
"limit": 50,
"offset": 0,
"count": 1,
"total": 1,
"has_more": false,
"next_offset": null
},
"updated_at": "2026-02-08T12:00:20Z",
"meta": {
"server_time": "2026-02-08T12:00:20Z"
}
}Cabeceras de Respuesta
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 299
X-RateLimit-Reset: 1737853200
X-Data-Delay: 0
X-Request-Id: req_delta_abc123Respuestas de Error
400 Falta el parámetro since
{
"error": {
"code": "validation_error",
"message": "The 'since' parameter is required for the delta endpoint",
"docs": "https://docs.sharpapi.io/en/api-reference/odds-delta"
}
}400 Offset demasiado grande
{
"error": {
"code": "offset_too_large",
"message": "offset must be <= 500; page with `next_offset` until `has_more` is false, then advance `since` to the response's top-level `updated_at` (mirrored as `meta.server_time`; a response field, not a row field) — it holds at your current `since` while `has_more` is true; keep paging while `next_offset` is non-null even if `overflow` is true (that only means `total` is capped); when `next_offset` is null while `has_more` or `overflow` is true, re-bootstrap from paged `/odds` (`cursor=`) and resume delta with a fresh `since`",
"max_offset": 500
}
}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"
}
}Esquema de Respuesta del Delta
El array data contiene los mismos objetos de cuotas que el endpoint /odds. Solo se incluyen las cuotas actualizadas después de la marca de tiempo since.
El Array removed
El array removed de nivel superior nombra cada fila de cuotas que salió del tablero desde tu marca de tiempo since — mercados que una casa retiró (suspensión, un umbral de hándicap/total retirado por un movimiento de línea, evento liquidado). Borra estos ids de tu estado local; esta es la señal de cierre explícita, así que nunca necesitas comparar snapshots tú mismo. Presente solo cuando al menos una eliminación coincidió con tus filtros. Consulta Ciclo de Vida del Mercado para el mapa completo de señales de cierre/suspensión.
| Campo | Tipo | Descripción |
|---|---|---|
removed[].id | string | El ID de la cuota que ya no está en el tablero |
removed[].sportsbook | string | La casa que la eliminó |
removed[].removed_at | string | Marca de tiempo ISO 8601 de cuándo SharpAPI observó la eliminación |
removed[].event_start | string | Opcional. Hora de inicio programada del evento, según la informó la casa deportiva al momento de la eliminación. Presente cuando la casa proporcionó una hora de inicio válida. |
removed[].was_live | boolean | Opcional. Si el mercado eliminado era un mercado en vivo al momento de la eliminación. false = pre-evento/prematch; true = en vivo/en juego. |
removed[].boundary | boolean | Opcional. Presente y true solo cuando was_live es false y la casa deportiva está publicando actualmente filas en vivo para este evento. Es una ayuda de filtrado, no un código de motivo ni un detector de transición determinista. Un mercado pre-evento eliminado horas después de que el evento se fue en vivo también puede recibir boundary: true. Ausente cuando was_live es true, el evento aún no está en vivo en esa casa, o la casa no proporciona datos en vivo. Los eventos de eliminación SSE/WS no cambian y no incluyen estos campos. |
La respuesta de delta incluye campos adicionales:
| Campo | Tipo | Descripción |
|---|---|---|
meta.server_time | string | Marca de agua en ISO 8601, reflejada como updated_at de nivel superior. Se mantiene en el since que enviaste mientras has_more sea true; solo en la página terminal (has_more: false) informa la marca de agua del servidor. Avanza tu since únicamente desde la página terminal |
meta.books_changed | array | Lista de IDs de casas de apuestas que tuvieron actualizaciones en este delta |
pagination.total | integer | Recuento exacto de cambios coincidentes en la página terminal. Mientras has_more sea true es una cota superior limitada a 10000 — no lo uses para progreso ni dimensionamiento antes de completar el recorrido |
pagination.next_cursor | null | Siempre null explícito en /odds/delta — este endpoint pagina con next_offset + since, nunca con cursores. Se emite explícitamente para que «aquí no hay cursor» sea distinguible de un campo ausente |
overflow | boolean | Opcional. Presente y true cuando total no es un recuento exacto para esta página — la cola bruta de candidatos superó el tope de 10000, o (nivel Free) el escaneo acotado del servidor se detuvo antes de cubrir toda la ventana. Las filas de data no se ven afectadas: sigue paginando mientras next_offset no sea null; total y overflow se corrigen en la página que drena. Rearranca cuando next_offset sea null mientras has_more u overflow sea true |
Indicadores de Truncado y Acotación
Aparecen dos indicadores booleanos opcionales de nivel superior solo cuando el servidor ha tenido que aplicar un límite de seguridad a la respuesta. Los clientes que se comportan correctamente y hacen polling a la cadencia recomendada nunca los ven.
| Campo | Tipo | Descripción |
|---|---|---|
removed_truncated | boolean | Presente y true cuando el array removed ha alcanzado el tope de 1000 entradas del servidor. Hay más cuotas eliminadas que el servidor no ha incluido. Normalmente significa que tu since es demasiado antiguo o tus filtros son demasiado amplios — reduce la ventana o el conjunto de filtros y vuelve a hacer polling. |
since_clamped | boolean | Presente y true cuando since era anterior a la retención de eliminaciones de 10 minutos del servidor. El array data aún respeta tu since original, pero removed queda restringido a las eliminaciones de los últimos 10 minutos. Avanza since en cada ciclo con el meta.server_time de la página terminal para evitarlo. |
Patrón de Polling
El patrón de polling recomendado drena cada ventana y luego encadena since desde la página terminal:
- Realiza una solicitud inicial con
sinceestablecido a una marca de tiempo reciente - Aplica
datacomo upserts yremovedcomo eliminaciones - Mientras
pagination.has_moreseatrueypagination.next_offsetno sea null, solicita la página siguiente conoffsetigual anext_offset, manteniendosincesin cambios - En la página terminal (
has_more: false), leemeta.server_timey úsalo como valorsinceen tu siguiente solicitud — salvo queoverflowsiga siendotrueen esa página (escaneo acotado del nivel Free): entonces rearranca en lugar de avanzar (ver abajo) - Repite en el intervalo deseado (p. ej., cada 5 segundos)
Esto garantiza:
- Sin huecos -
server_timees el reloj del servidor y solo avanza cuando ya tienes todas las filas de la ventana, así que no perderás actualizaciones por desfases de reloj ni por una lectura parcial - Sin duplicados - cada ventana de delta no se solapa con las demás
- Carga útil mínima - solo se devuelven las cuotas que han cambiado
Avanzar since desde una página con has_more: true no puede saltarse datos — meta.server_time es igual a tu since actual en esas páginas — pero detiene el progreso de tu bucle: la siguiente solicitud vuelve a leer la misma ventana. Drena siempre hasta la página terminal antes de avanzar since.
Cuando una ventana no se puede drenar
offset está limitado a 500, así que una ventana con más cambios coincidentes de los que la paginación por offset puede alcanzar termina con next_offset: null mientras has_more sigue siendo true. En el nivel Free, el escaneo acotado del servidor puede además dejar overflow: true en la propia página terminal (has_more: false) — las filas más allá del presupuesto de escaneo son inalcanzables con cualquier offset, y avanzar since ahí las saltaría. Ambos estados son la misma señal — rearranca siempre que next_offset sea null mientras has_more u overflow sea true:
- Obtén una base completa desde
/oddscon paginacióncursor= - Reanuda el polling de delta con
sinceestablecido alupdated_atde la primera página de la base — las páginas posteriores se leen más tarde; usar el valor de la última página dejaría huecos con los cambios que llegaron a páginas anteriores durante el rastreo
Haciendo polling a la cadencia recomendada con limit=500, las ventanas se mantienen lo bastante pequeñas como para que esta ruta rara vez sea necesaria.
Si ninguna cuota ha cambiado desde tu marca de tiempo since, la respuesta tendrá un array data vacío y count: 0. Esto es normal y esperado durante períodos de poca actividad.
Endpoints Relacionados
- Instantánea de Cuotas - Obtén la instantánea completa actual de cuotas
- SSE Stream - Actualizaciones push en tiempo real mediante Server-Sent Events
- WebSocket Stream - Actualizaciones push en tiempo real mediante WebSocket