Respuesta rápida
Con una clave de Odds-API.io y unas 40 líneas de Python puedes listar eventos, traer precios de varias casas, convertirlos en probabilidades implícitas y recibir actualizaciones en vivo. La URL base REST es https://api.odds-api.io/v3 y la clave va en el parámetro apiKey [1] [2].
Qué necesitas
Qué necesitas: Python 3.9+, los paquetes requests y websockets y una clave de API. Las claves gratuitas nuevas están en pausa; los planes empiezan en 49 £ al mes con 2 casas y 5.000 peticiones por hora [1] [3].
Consigue una clave: Odds-API.io Enlace de socio
Enlace de socio — podríamos recibir una comisión. Consulta nuestra divulgación de afiliados.
Estado del código: El código Python de este tutorial se ejecutó con las respuestas de ejemplo publicadas en la documentación de Odds-API.io (comprobadas el 3 de noviembre de 2026), no con una clave real. Las respuestas reales pueden traer más campos; el código solo lee los documentados.
1. Instala los paquetes y guarda tu clave
Guarda la clave en una variable de entorno, no en el código [1].
python -m pip install requests websockets
export ODDS_API_KEY="your-api-key" # Windows PowerShell: $env:ODDS_API_KEY="your-api-key"
2. Lista deportes y próximos eventos
/sports no necesita clave. /events recibe un deporte y, de forma opcional, league, status (p. ej. pending, live), un rango de fechas y limit [4].
import os
import requests
BASE = "https://api.odds-api.io/v3"
API_KEY = os.environ["ODDS_API_KEY"] # never hard-code or commit your key
BOOKMAKERS = "Bet365,Unibet" # use bookmakers selected on your plan
def get(path, **params):
"""GET an Odds-API.io v3 endpoint and return parsed JSON."""
params["apiKey"] = API_KEY
r = requests.get(BASE + path, params=params, timeout=20)
if r.status_code == 429:
raise RuntimeError("Rate limit reached - wait before retrying")
r.raise_for_status()
return r.json()
sports = requests.get(BASE + "/sports", timeout=20).json() # no key needed
print([s["slug"] for s in sports][:10])
events = get("/events", sport="football", league="england-premier-league",
status="pending", limit=10)
for e in events:
print(e["id"], e["date"], e["home"], "v", e["away"])
3. Obtén cuotas y calcula la probabilidad implícita
/odds recibe un eventId, hasta 30 bookmakers y un filtro opcional markets; los precios son cadenas decimales [4] [1]. El código los convierte en probabilidades implícitas, quita el Overround de forma proporcional y busca el mejor precio de cada resultado: las mismas matemáticas que la Calculadora de probabilidad implícita y sin margen.
def ml_prices(event_odds):
"""{bookmaker: {"home": 2.1, "draw": 3.4, "away": 3.2}} from one /odds response."""
out = {}
for book, markets in event_odds.get("bookmakers", {}).items():
for m in markets:
if m["name"] == "ML" and m.get("odds"):
row = m["odds"][0]
out[book] = {k: float(row[k]) for k in ("home", "draw", "away") if k in row}
return out
event_id = events[0]["id"]
prices = ml_prices(get("/odds", eventId=event_id, bookmakers=BOOKMAKERS, markets="ML"))
for book, p in prices.items():
booksum = sum(1 / o for o in p.values()) # implied probabilities
fair = {side: (1 / o) / booksum for side, o in p.items()} # proportional no-vig
print(f"{book}: overround {booksum - 1:.2%}",
{side: f"{q:.1%}" for side, q in fair.items()})
best = {}
for book, p in prices.items():
for side, o in p.items():
if o > best.get(side, (0, ""))[0]:
best[side] = (o, book)
print("Best price per outcome:", best)Con la respuesta de ejemplo de la documentación (Bet365 2,10 / 3,40 / 3,20) muestra un overround del 8,28 %.
4. Agrupa hasta 10 eventos en una petición
/odds/multi devuelve cuotas de hasta 10 eventos y cuenta como una sola petición, algo importante con un límite de 5.000 peticiones por hora [4] [3].
ids = ",".join(str(e["id"]) for e in events[:10]) # up to 10 events
for ev in get("/odds/multi", eventIds=ids, bookmakers=BOOKMAKERS, markets="ML"):
print(ev["home"], "v", ev["away"], ml_prices(ev))
5. Recibe precios en vivo por WebSocket
Para precios que cambian durante el partido, usa el Feed WebSocket en wss://api.odds-api.io/v3/ws. El filtro markets es obligatorio, la conexión debe admitir permessage-deflate (websockets de Python lo hace; websocket-client se rechaza) y cada mensaje updated trae el conjunto completo de mercados, así que sustituye lo guardado en lugar de combinarlo [5]. El WebSocket es un complemento de pago [3].
import asyncio, json, os
from urllib.parse import urlencode
import websockets # needs permessage-deflate; "websocket-client" is refused
STATE = {} # (event id, bookmaker) -> list of markets
async def stream():
qs = urlencode({"apiKey": os.environ["ODDS_API_KEY"], "markets": "ML",
"sport": "football", "status": "live"})
async with websockets.connect(f"wss://api.odds-api.io/v3/ws?{qs}",
ping_interval=30, ping_timeout=10) as ws:
async for raw in ws:
msg = json.loads(raw)
if msg["type"] in ("created", "updated"):
STATE[(msg["id"], msg["bookie"])] = msg["markets"] # replace, never merge
for m in msg["markets"]:
if m["name"] == "ML" and m.get("odds"):
print(msg["id"], msg["bookie"], m["odds"][0])
elif msg["type"] in ("deleted", "no_markets"):
STATE.pop((msg["id"], msg["bookie"]), None)
asyncio.run(stream())
6. Siguientes pasos
Pasa los precios a la Calculadora de arbitraje o a la Calculadora de valor esperado (+EV), o deja que la API haga el cálculo: consulta Buscador de arbitraje y +EV con Odds-API.io. Para comparar con Polymarket y Kalshi, lee Mercados de predicción frente a cuotas de casas.
Preguntas frecuentes
¿Necesito un plan de pago?
Sí, si eres nuevo: las claves gratuitas nuevas están en pausa y los planes empiezan en 49 £ al mes. Las claves gratuitas existentes siguen funcionando con 100 peticiones por hora y un máximo de 500 al día.
¿Qué casas puedo consultar?
Las que tengas seleccionadas en tu plan. Si pides otras, no se devuelven.
¿REST o WebSocket?
REST para instantáneas y consultas puntuales; WebSocket para precios siempre actualizados. La documentación recomienda el WebSocket para datos en vivo.
Sobre esta guía
Pred-Data publica guías independientes y con fuentes enlazadas sobre los mercados de predicción y las herramientas de IA que se usan en ellos. Cada dato enlaza a una fuente primaria o secundaria fiable, verificada en la fecha indicada arriba. No operamos ninguna plataforma de trading, no aceptamos apuestas ni damos asesoramiento personal.
Autor: Ken Lin · Correcciones: si detectas un error, lo revisaremos y fecharemos la corrección.
Divulgación de afiliados
Algunos enlaces de este sitio (marcados como «Enlace de socio») pueden ser enlaces de afiliado: si te registras a través de ellos, podríamos recibir una comisión sin coste adicional para ti. Estos enlaces usan rel="sponsored nofollow" y nunca cambian nuestra valoración. Los enlaces a plataformas en las tablas comparativas son enlaces normales, no de afiliado, a sus webs oficiales.
Fuentes
- Quickstart (get a key, first calls, example responses) — Odds-API.io docs, consultado el 2 nov 2026
- AI & Vibe Coding (llms.txt, OpenAPI, copy-paste context, MCP setup) — Odds-API.io docs, consultado el 2 nov 2026
- Odds API Pricing (plans, WebSocket add-on, extra requests, payment) — Odds-API.io, consultado el 2 nov 2026
- OpenAPI specification (all v3 endpoints and parameters) — Odds-API.io docs, consultado el 2 nov 2026
- WebSocket guide (wss://api.odds-api.io/v3/ws, markets filter, reconnects) — Odds-API.io docs, consultado el 2 nov 2026