On this page
  1. The three delivery models
  2. REST polling with since cursors
  3. SSE alerts
  4. Raw WebSocket
  5. Latency, cost and complexity
  6. The one-connection-per-key rule
  7. Which one fits your project

Every odds feed has to answer one architectural question before anything else: does your code ask for data, or does data arrive? The old Pinnacle API only supported asking, with a fair-use limit that made asking often impossible. Modern feeds offer both. This guide compares REST polling, Server-Sent Events and raw WebSocket on latency, cost and complexity, using pinnodds as the concrete example because it offers all three. For code, we point to pinnacleapi.dev.

The three delivery models

REST polling means your client requests a snapshot or a delta on a timer. SSE means the server pushes a filtered stream of events over a long-lived HTTP connection. WebSocket means a bidirectional socket carries every upstream frame as it arrives. They differ in who decides when data moves and in how much of it moves.

Scroll for more

REST polling, SSE and WebSocket compared on who initiates, what arrives, what bounds them and typical use
ModelWho initiatesWhat arrivesBounded byTypical use
REST pollingClient, on a scheduleFull board or delta since a cursorPlan rate limit and your intervalDashboards, research, batch models
SSEServer, on detected eventsDrop alerts with from/to price, nvp, limitOne connection per keyAlert bots, triggers
WebSocketServer, on every changeRaw upstream framesOne connection per key; add-on on some plansCustom detection, mirrors, archives

REST polling with since cursors

Polling is a loop: request the board, sleep, repeat. A since cursor turns each request into a delta, so the server returns only what changed after the value you passed back from the previous response. Deltas keep responses small and make frequent polling cheap in bandwidth, but each request still counts against your rate limit.

The pattern is the same as it was with the old Pinnacle API, which is why polling code migrates easily. On pinnodds both the markets endpoint and the prematch fixtures endpoint accept since and return a last value. Your effective latency is your polling interval plus one round trip, so a 60-second loop sees a change up to a minute late. Shortening the interval improves that linearly and eats quota linearly: at 20 requests a minute on the Trial or Stream plan you can poll one sport every three seconds, while at 10 requests a second on Pro you can poll several sports every second. Full quickstarts are on pinnacleapi.dev/python and pinnacleapi.dev/nodejs.

poll.py
# Poll every 60 s with a delta cursor (Python, pinnodds SDK)
from pinnodds import Client, SPORTS
import time

api = Client("YOUR_KEY")
last = None
while True:
    resp = api.markets(sport_id=SPORTS["soccer"], event_type="prematch", since=last)
    last = resp.get("last") or last
    handle(resp["events"])
    time.sleep(60)

SSE alerts

Server-Sent Events is a plain HTTP response that never ends; the server writes an event whenever it has something to say. In an odds feed that something is usually a detected drop: the provider compares prices upstream and sends you only the changes above your threshold, with the before and after prices and the no-vig price attached.

SSE is the sweet spot for alert bots. It uses ordinary HTTP, works through most proxies, reconnects easily and requires no protocol beyond reading lines. On pinnodds the SDKs expose it as an iterator, stream_drops in Python and streamDrops in Node, with a minimum-drop filter and a mode for live or prematch. The alert fields differ from the REST drop rows: you get sect, outcome, from_price, to_price, id, limit and nvp, and you derive the percentage yourself. SSE is included on the Stream, Pro + SSE and Scale plans and on the 3-day demo, but not on the plain Pro plan. A curl and Python walkthrough is at pinnacleapi.dev/sse, and pinnodds has an end-to-end Telegram alert bot tutorial.

sse_alerts.py
# SSE drop alerts: the server tells you when a price drops (Python)
from pinnodds import Client

api = Client("YOUR_KEY")
for d in api.stream_drops(min_drop=5):
    notify(d["home"], d["away"], d["sect"], d["outcome"], d["from_price"], d["to_price"])

Raw WebSocket

A raw WebSocket relays every upstream price frame the moment it arrives, with no filtering. You receive the whole firehose and decide what matters. It gives the lowest possible latency and the most information, at the cost of handling volume, parsing and reconnection yourself.

This is the model for people who want to build their own detection logic, mirror the board into a local store, or record everything for later analysis. On pinnodds the endpoint is wss://pinnodds.com/ws/feed?key=KEY, and it is a paid add-on on eligible plans rather than part of the base tiers. Any WebSocket library works; the Node ws package and the Python websockets package are the usual choices. Expect to write a reconnect loop with backoff, a heartbeat check, and enough state to detect gaps after a reconnect. The connection guide with reconnect handling is at pinnacleapi.dev/websocket; the provider's own description is on its WebSocket API page.

ws-feed.mjs
// Raw WebSocket: every upstream frame, you do the detection (Node, ws package)
import WebSocket from "ws";
const ws = new WebSocket("wss://pinnodds.com/ws/feed?key=" + process.env.PINNODDS_KEY);
ws.on("message", (buf) => { const frame = JSON.parse(buf.toString()); handle(frame); });
ws.on("close", () => setTimeout(reconnect, 2000));

Latency, cost and complexity

Polling is the simplest and the slowest; SSE is nearly as simple and close to real time for the events it covers; WebSocket is the fastest and the most work. Cost follows the same order in a different way: polling spends requests, push spends engineering.

  • Latency. Polling latency equals your interval plus a round trip, so it is a design choice bounded by quota. Push latency is the provider's detection time plus network delivery, typically well under a second, though the exact figure depends on the provider and your location. pinnodds discusses what "fast" means for an odds feed in How fast is an odds feed.
  • Cost. Polling faster means a bigger plan. Pushing costs nothing per event but may require a plan with SSE or the WebSocket add-on, and one connection per key. Our pricing page maps workloads to plans.
  • Complexity. A polling loop is ten lines and stateless apart from the cursor. SSE adds a reconnect. WebSocket adds reconnect, heartbeat, gap detection, and all of the change detection the server would otherwise do for you.
  • Coverage. Polling and WebSocket give you the whole board. SSE, at least in the drop-alert form, gives you only the changes that pass a filter, so it cannot rebuild the board on its own. Most alert bots pair SSE with an occasional REST call for context.

The one-connection-per-key rule

Three patterns follow from it. Run a single consumer per key and fan out internally, for example by writing to a queue or a local pub/sub that your other processes read. Or hold one key per consumer if the processes are independent. Or, if you have several bots that all need the same stream, run one relay process that owns the connection and re-broadcasts. The rule also means a redeploy briefly disconnects your stream: build the reconnect so the new process taking over is expected behavior, not an error.

Which one fits your project

Use polling for anything that refreshes on a human timescale, SSE for anything that reacts to a drop, and WebSocket when you need every frame or want to own the detection logic. Many production systems use two: SSE or WebSocket for the trigger, REST for the detail.

Polling fits

  • Dashboards and research notebooks refreshed every minute or more.
  • Batch models that snapshot a board on a schedule.
  • Code migrated from the old Pinnacle API that already has a since loop.

SSE fits

  • Drop-alert bots for Telegram or Discord.
  • Triggers that kick off a REST lookup when a price moves.
  • Anything where the provider's drop detection is good enough.

WebSocket fits

  • Custom change detection with your own thresholds and logic.
  • Mirroring the whole board into a local store in real time.
  • Recording a full archive of price movement for research.

Not sure

  • Start with polling on the free Trial to learn the data.
  • Use the 3-day demo, which includes SSE, to prototype the push version.
  • Measure your real request rate before choosing a paid plan.

Whichever model you choose, the data conventions are the same, and our guide to reading Pinnacle lines covers them. To try all three transports against real prices, get a free pinnodds trial key and follow the get-started steps. If you are still choosing a provider, the alternatives comparison lists which transports each one offers.