On the wire · 04:57:15 UTC Live 567 · Prematch 14,380 · Markets 56,882 Vol. I · No. 5 · Friday 13 November 2026 wss://pinnfeed.io/v1/stream
PinnFeed
Respuesta · Python · pandas

Cuotas de Pinnacle en un DataFrame de pandas

Actualizado el · PinnFeed · 2 min de lectura

Respuesta: llama a GET /v1/odds y recorre eventos → mercados → resultados para crear una fila por resultado. Obtienes un DataFrame ordenado con decimal, fair, fairProb, margin y maxStake por precio, listo para groupby, Parquet o un notebook. Funciona en todos los planes; en Free los datos llevan 30 segundos de retraso.

Código#

# pip install requests pandas
import os, requests, pandas as pd

r = requests.get(
    "https://pinnfeed.io/v1/odds",
    headers={"x-api-key": os.environ["PINNFEED_KEY"]},  # ps_live_...
    params={"sport": "soccer", "main": "true", "limit": 200},
    timeout=20,
)
r.raise_for_status()

rows = []
for ev in r.json()["events"]:
    for m in ev.get("markets", []):
        for o in m.get("outcomes", []):
            rows.append({
                "event_id": ev["id"], "start": ev.get("startTime"), "live": ev.get("live"),
                "league": (ev.get("league") or {}).get("name"),
                "home": ev.get("home"), "away": ev.get("away"),
                "market": m.get("type"), "period": m.get("period"), "line": m.get("line"),
                "margin": m.get("margin"), "max_stake": m.get("maxStake"),
                "outcome": o.get("name"), "decimal": o.get("decimal"),
                "fair": o.get("fair"), "fair_prob": o.get("fairProb"),
            })

df = pd.DataFrame(rows)
df["start"] = pd.to_datetime(df["start"], utc=True)
print(df.groupby("market")["margin"].describe())
df.to_csv("pinnacle_soccer.csv", index=False)

Siguientes pasos#

Planes#

Free (€0): 30 s de retraso, 2 deportes, mercados principales, 1.000 peticiones al día. Hobby (€29/mes): REST en tiempo real. Builder (€99/mes): WebSocket, todos los mercados e histórico de cierres. Prueba de 3 días; se requiere tarjeta y se cobra después del día 3 salvo que canceles.

Contenido educativo para mayores de 18 años. Para investigación y modelos, no es consejo de apuestas. En España, apuesta solo con operadores con licencia de la DGOJ.

Preguntas frecuentes#

¿Por qué una fila por resultado?#

Así cada precio está en una sola columna y los filtros, tablas dinámicas y joins son sencillos. Para una fila por mercado: df.pivot_table(index=["event_id","market","line"], columns="outcome", values="decimal").

¿Funciona en Jupyter o Colab?#

Sí. Define la clave con os.environ["PINNFEED_KEY"] = "ps_live_..." en una celda que no compartas.

¿Hay versión con polars?#

Pasa la misma lista rows a polars.DataFrame(rows).

El plan WebSocket: Builder, 99 €/mes.

Cuotas de Pinnacle en tiempo real por un único WebSocket: los 13 deportes, todos los mercados, cuotas justas sin margen y cuotas de cierre. 3 días gratis y cancelas con un clic.

Form K-1 · Free API key

Get your free API key.

One field. No password, no card: enter your email, click the link we send, and your key is on screen.

By continuing you agree to the Terms and Privacy Policy.

One free key per email. Link valid for 20 minutes.