Captured at kickoff
When an event goes live (or its start time passes) we snapshot every open market — moneyline, spreads, totals, team totals and periods — including margin, max stake and fair prices.
The closing line is the most efficient price a market produces. PinnFeed records the last prematch price of every Pinnacle market at kickoff and serves it by event or by day.
When an event goes live (or its start time passes) we snapshot every open market — moneyline, spreads, totals, team totals and periods — including margin, max stake and fair prices.
GET /v1/closing/{eventId} returns all closing markets for an event; GET /v1/closing?date=YYYY-MM-DD&sport=soccer pages through a whole day.
Compare the price you bet with the fair closing price. Consistently beating the close is the strongest evidence that a betting model has an edge.
Enterprise plans include CSV/Parquet exports of the whole archive for research and model training.
# pip install websockets
import asyncio, json, os, websockets
async def main():
url = "wss://pinnfeed.io/v1/stream"
async with websockets.connect(url, additional_headers={"x-api-key": os.environ["PINNSOCKET_KEY"]}) as ws:
await ws.send(json.dumps({"type": "subscribe", "sports": ["soccer"], "live": True}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "ping": await ws.send('{"type":"pong"}')
elif msg["type"] == "delta":
for c in msg["changes"]:
if c["kind"] == "market" and c["op"] == "upsert":
m = c["market"]; print(m["key"], [(o["name"], o["decimal"], o["fair"]) for o in m["outcomes"]])
asyncio.run(main())// npm install ws
import WebSocket from 'ws';
const ws = new WebSocket('wss://pinnfeed.io/v1/stream', {
headers: { 'x-api-key': process.env.PINNSOCKET_KEY }, perMessageDeflate: true,
});
ws.on('open', () => ws.send(JSON.stringify({ type: 'subscribe', sports: ['tennis', 'basketball'] })));
ws.on('message', (buf) => {
const msg = JSON.parse(buf);
if (msg.type === 'ping') return ws.send('{"type":"pong"}');
if (msg.type === 'delta') for (const c of msg.changes) console.log(c.kind, c.op, c.market?.key ?? c.event?.home);
});# REST snapshot: every live soccer event with main markets
curl -H "x-api-key: $PINNSOCKET_KEY" \
"https://pinnfeed.io/v1/odds?sport=soccer&live=true&main=true"
# Closing lines for yesterday (Builder and above)
curl -H "x-api-key: $PINNSOCKET_KEY" \
"https://pinnfeed.io/v1/closing?date=2026-11-08&sport=tennis"{
"type": "delta", "seq": 48213, "ts": 1762679412093,
"changes": [{
"kind": "market", "op": "upsert",
"market": {
"id": "1640278226:s;0;m", "eventId": 1640278226,
"type": "moneyline", "period": 0, "main": true, "live": true,
"margin": 0.0357, "maxStake": 1500,
"outcomes": [
{ "name": "home", "american": -128, "decimal": 1.781, "fair": 1.845, "fairProb": 0.5421 },
{ "name": "draw", "american": 262, "decimal": 3.62, "fair": 3.750, "fairProb": 0.2667 },
{ "name": "away", "american": 405, "decimal": 5.05, "fair": 5.230, "fairProb": 0.1912 }
]
}
}]
}The archive starts on the day the service launched and grows every day.
No. Closing-line history is included from the Builder plan.
Delayed REST data free forever. Real-time WebSocket from $29/mo.