pnclPULSEGet API access

SSE SETUP

Connect the Pinnacle API SSE drop stream.

One HTTPS request to the Pinnacle odds API that never finishes. The server writes drop events to it as Pinnacle prices fall, and your client reads, filters and reconnects. This page covers the connection, the frame format, and where your rule state belongs.

Opening the Pinnacle API stream

The stream is plain HTTPS. Send a GET to /odds-drop for live markets or /odds-drop-prematch for prematch ones, with your key in the x-portal-apikey header or as ?key=. Set min_drop yourself rather than relying on the default: the documented example uses 5, and it goes as low as 1. A 200 response with a text/event-stream content type means the connection now stays open and alerts arrive as drops are detected.

GET /odds-drop?min_drop=5 HTTP/1.1
Host: <api host from the docs>
Accept: text/event-stream
x-portal-apikey: <your key>

Any HTTP client that reads a response incrementally works: curl for a smoke test, your language's HTTP library in production. The browser's EventSource can connect with ?key=, but that puts the key in a URL every visitor can read, so run the reader server-side. Each account gets one connection per stream: a second live connection with the same key closes the first, while a live and a prematch connection can run side by side. On the prematch stream, recheck=N holds each drop for N seconds and sends it only if the price has not bounced back.

Event shape

Every message is a data: line. The first is a control object; after it, each batch of alerts is a JSON array. This is the documented example, trimmed:

data: {"type": "connected", "id": "d648beb8-..."}
data: [{"home": "Sunshine Coast Phoenix", "away": "Cairns Dolphins", "league": "Australia - NBL1 Women", "sport": "Basketball", "sect": "Moneyline", "outcome": "Home", "period": 4, "from_price": 2.86, "to_price": 2.7, "nvp": 3.04, "id": 1629729400, "alerted": 1777625196, ...}]

Parse each data: line as JSON. An object is a control message: connected when the stream opens, or an error such as plan_lacks_sse when the key's plan has no stream. An array is a batch of alerts. Each alert names the line with sport, league, sect, outcome and period, carries the price before and after as from_price and to_price, adds nvp, the no-vig fair price after the move, and stamps the alert time in Unix seconds as alerted. The percentage is yours to compute: (2.86 − 2.70) ÷ 2.86 = 5.6%.

Reconnects and quiet periods

Connections die: proxies idle out, networks flap, deploys happen. Reconnect with a pause that grows after each failure. A client that reconnects in a tight loop gets a single rate_limited error frame with a Retry-After: 60 header, so honor it instead of hammering the endpoint.

Missed alerts are not replayed: the documentation promises no resume point, so treat anything that fell during the gap as missed. When a gap matters, fill it from the REST drops endpoint, which keeps recent drops for up to about three hours with a timestamp on each.

Quiet stretches are normal, prematch especially. To tell a quiet market from a broken feed, poll the health endpoint alongside the stream: it reports how long ago the live feed last wrote. If that age keeps growing while your connection says nothing, close it and reconnect.

Keeping rule state server-side

Thresholds, seen-alert sets and dedupe windows belong on the server, not in a browser tab that can sleep or close. The reader process owns the connection; whatever evaluates your rules should sit next to it.

Make processing idempotent. Build the dedupe key from id, sect, outcome, period and alerted rather than from one field, and drop duplicates before your rule runs. Persist the last alert time you processed along with your rule state, and a restart resumes cleanly instead of re-alerting on moves you already handled.

When raw frames beat SSE

SSE is the right default for alerting: the stream detects the drops, and your client only handles events that already crossed a line. Choose raw WebSocket when your application needs every frame, because you rebuild the full market state yourself instead of consuming finished drop events. That covers tracking books that have not moved enough to alert, or applying detection logic the drop stream was never meant to run. The raw WebSocket add-on is $99 per 30 days on REST and combined plans. If your rule only reacts to drops, stay on SSE; everything on this page still applies.

See plans with WebSocket

Test your rule first

Before you hold a connection open, check the rule on paper. The drop alerts guide covers the percentage formula and how thresholds, windows and filters compose. Streaming access options are listed under plans.

When the rule holds up on paper, connect the stream and let it run.

If you would rather start from working code, the Python quickstart on pnclFEED has an SSE listener that reads this stream as it is.

Get API access