Quickstart

PinnFeed streams Pinnacle odds to your code over one WebSocket and a REST API. This page takes you from zero to live prices in about five minutes.

1. Get an API key#

  1. Create a free account with your email and a password.
  2. Open the dashboard and click Create key. Copy the key: it is shown once and starts with ps_live_.
  3. Store it in an environment variable:
export PINNSOCKET_KEY="ps_live_..."

The Free plan works with REST (30-second delay). The real-time WebSocket needs Hobby or above — see pricing.

2. Make a REST call#

curl -H "x-api-key: $PINNSOCKET_KEY" "https://pinnfeed.io/v1/odds?sport=soccer&main=true&limit=5"

You get events with their markets. Every outcome has an American price, a decimal price and a no-vig fair price. The full field list is in the schema reference.

3. Open the WebSocket#

# pip install websockets
import asyncio, json, os, websockets

async def main():
    async with websockets.connect(
        "wss://pinnfeed.io/v1/stream",
        additional_headers={"x-api-key": os.environ["PINNSOCKET_KEY"]},
        compression="deflate",
    ) as ws:
        await ws.send(json.dumps({"type": "subscribe", "sports": ["soccer", "tennis"], "live": True}))
        async for raw in ws:
            msg = json.loads(raw)
            if msg["type"] == "ping":
                await ws.send('{"type":"pong"}')
            elif msg["type"] == "snapshot":
                print("snapshot part", msg["part"], "/", msg["parts"], len(msg["markets"]), "markets")
            elif msg["type"] == "delta":
                for c in msg["changes"]:
                    if c["kind"] == "market" and c["op"] == "upsert":
                        m = c["market"]
                        print(m["eventId"], m["key"], [(o["name"], o["decimal"]) for o in m["outcomes"]])

asyncio.run(main())

You first receive a welcome message, then a chunked snapshot of everything that matches your filters, then a stream of delta batches. See the WebSocket protocol for every message type.

4. Keep a local book#

Apply each change to a dictionary keyed by market.id (and event.id for events):

  • op: "upsert" — replace the object.
  • op: "remove" — delete it (the market was suspended or settled, or the event ended).

That is the whole client-side state machine. More languages are in examples.

Not a developer? Pinnacle Terminal gives you live odds screens, dropping-odds alerts and steam moves without writing code.