Developer guide · Live and in-play odds · Updated August 26, 2026

Live betting odds API: build on a Pinnacle in-play feed

Live betting software needs more than a number that changes. It needs current market snapshots, a way to receive important movement, freshness you can verify, and explicit behavior when a market pauses or closes. PinnWire gives you that complete path for real-time Pinnacle live odds.

Short answer: use PinnWire as the live betting odds API layer. Start with REST for current Pinnacle in-play snapshots and recovery, add SSE when you want server-detected live price-drop alerts, and use the optional raw WebSocket when your application needs subscribed live and prematch market updates. Check generated_at, treat state as optional, handle closures explicitly, and keep execution or settlement outside the data layer.

What a live betting odds API has to deliver

Live betting, also called in-play betting, begins after an event starts. Prices respond to the changing market and the information published by the sportsbook feed. For a software product, the difficult part is not rendering a red or green number; it is preserving the identity and status of each market while updates arrive at different times.

Current

Know the present book

Fetch live event and market snapshots with decimal prices, periods, event identity, and a response-generation timestamp.

Change

Notice meaningful movement

Receive detected live price drops through SSE, or subscribe to the raw stream when your model needs every update for selected events.

Control

Know when to pause

Handle suspensions, closed periods, deletes, stale connections, and missing optional state without guessing or filling gaps.

A live betting odds API is not a bet-placement API. PinnWire supplies current Pinnacle reference data for dashboards, alerting, model inputs, market monitors, and decision-support systems. Your application remains responsible for authorization, local rules, risk controls, any execution integration, and settlement.

Important boundary: do not treat a live feed as a universal scoreboard. PinnWire includes live state when the feed publishes it, but state is sport-specific and optional. A missing score is not a score of zero, and a missing state object is not proof that the event is not live.

Why PinnWire is the strongest fit for live Pinnacle data

PinnWire is built around one clear job: make current Pinnacle odds useful to your application. The product keeps the simple path simple, then gives you a higher-volume push path when your live workflow needs it. You can prove the REST feed with the public demo, move to a free trial, and select the transport that matches your workload.

SurfaceWhat it deliversUse it forAccess
RESTCurrent JSON snapshots of live markets and event detailsDashboards, reads, recovery, periodic model inputsAll plans; public demo is REST-only
SSEServer-detected live price-drop alertsDrop notifications, movement screens, lightweight event triggersStream and higher plans
Raw WebSocketSubscribed live and prematch update frames after a baseline snapshotLocal odds books, high-volume monitoring, continuous model featuresWebSocket add-on

This separation makes a live betting data system easier to reason about: REST is the source for a known snapshot, SSE is a focused alert stream, and WebSocket is the full update stream. PinnWire does not force every consumer to process full-feed volume when a current read or a drop alert is enough.

REST: current Pinnacle in-play snapshots

The fastest way to test a Pinnacle in-play odds API is a REST request. The compatibility endpoint below returns live markets for a sport. Use a real trial or paid key for ongoing application traffic; the public demo is intentionally small.

Current live soccer markets · public demo
curl "https://pinnwire.com/kit/v1/markets?sport_id=1&key=demo&fresh=live-test-1"

# Read generated_at on every response.
# Live state appears only when the feed publishes it.

For a single match, use GET /kit/v1/details?event_id=N&key=YOUR_KEY. For a client rebuilding after a dropped connection, fetch the relevant live snapshot again and replace the local view from that response. Do not keep making decisions from an uncertain, partially updated book.

Freshness

generated_at

ISO-8601 time at which PinnWire generated the response. It is a response timestamp, not a source-publication timestamp.

Feed activity

last_odds_update_seconds_ago

Health metadata that helps a client judge whether the feed has updated recently. Define your own acceptable age for the workflow.

Live state is useful, but defensive parsing is required

When available, the live response can include a match state and participant state. Soccer may publish a state and minutes; other sports can publish different fields. Iterate over fields defensively, display a clear “state unavailable” treatment if needed, and never invent a score or period from a missing property.

Minimal JavaScript snapshot check
const url = "https://pinnwire.com/kit/v1/markets?sport_id=1&key=YOUR_KEY&fresh=" + crypto.randomUUID();
const response = await fetch(url, { cache: "no-store" });
if (!response.ok) throw new Error(`PinnWire HTTP ${response.status}`);

const book = await response.json();
console.log({
  generatedAt: book.generated_at,
  events: book.events?.length ?? 0,
  firstState: book.events?.[0]?.state ?? null
});

PinnWire uses decimal odds in the compatibility response. Match event ID, market key, period, side, points, and response freshness before joining an update to your own records.

SSE: detected live odds-drop alerts

If your live betting product cares about a price falling rather than every market update, PinnWire’s SSE surface is the cleanest option. /odds-drop is the live-only stream; each event is a detected price drop with market context and the no-vig reference field nvp.

Listen for live drops
curl -N "https://pinnwire.com/odds-drop?key=YOUR_KEY&min_drop=5"

data: {"type":"connected","id":"..."}
data: [{"event_id":123,"market":"spread","period":0,
        "side":"home","from_price":2.40,"to_price":2.26,
        "drop_pct":5.83,"nvp":2.31,"is_live":true}]

min_drop=N sets the percentage threshold for that connection; the floor is 1%. REST drop records use from and to, while SSE keeps its wire names from_price and to_price. Keep-alive comments are normal and should be ignored.

PinnWire’s advantage for alert workflows: the server does the drop detection and attaches the event, market, side, period, movement, live flag, and fair-price context. Your consumer can react to a structured candidate instead of polling every event and calculating every change itself.

What an alert does not mean

A detected drop is movement, not a promise of value, execution, or market intent. Re-fetch the current market when your decision requires it, confirm that the exact contract still matches, check your own authorized executable price and limit, and store the alert timestamp. The nvp field is a no-vig reference estimate; it is not a guarantee.

Raw WebSocket: a real-time live odds feed for your own book

Choose PinnWire’s optional raw WebSocket when your application needs the complete update stream for selected live events. The connection begins with a subscription and a baseline snapshot, then receives continuous adds, updates, and deletes for the subscribed scope. It supports both live and prematch streams.

Subscribe by sport or event
wss://pinnwire.com/ws?key=YOUR_KEY

// Send within 10 seconds of connecting:
{"type":"subscribe","streams":["live"],"sport_ids":[1,3],"event_ids":[1631005165]}

// Reply to the server heartbeat:
{"type":"pong"}

Sport subscriptions cover the events in that sport; event subscriptions can target up to 200 event IDs per stream. Every subscription is acknowledged, and matching events are returned in a snapshot before ongoing frames. Large snapshots can be split into chunks with seq and final markers.

Message or fieldClient behavior
subscribed / unsubscribedRecord the server’s acknowledgement before assuming a scope is active.
snapshotUse it as the baseline for your local book; apply update frames after it.
live with op add/upd/delMerge by record and market identity; delete closed records instead of leaving stale prices.
prematch_ws and related prematch framesHandle the same subscription model for prematch updates; do not assume every frame is a live event.
ping with buffered_max_bytesReply with pong and record the backlog high-water mark for backpressure monitoring.
Small Node.js consumer skeleton
import WebSocket from "ws";

const ws = new WebSocket("wss://pinnwire.com/ws?key=YOUR_KEY");
ws.on("open", () => ws.send(JSON.stringify({
  type: "subscribe", streams: ["live"], sport_ids: [1]
})));
ws.on("message", raw => {
  const msg = JSON.parse(raw);
  if (msg.type === "ping") return ws.send(JSON.stringify({type: "pong"}));
  if (msg.type === "snapshot") return rebuildBook(msg);
  if (msg.type === "live") return mergeUpdate(msg); // add/upd/del
});
ws.on("close", (code, reason) => scheduleReconnect(code, reason));

For exact merge rules, key records by rec.id and the market key, deduplicate on markets[i].version, and use the ld price channel as the live price. A reconnect receives a new snapshot; the server does not preserve your client session.

Freshness, suspensions, closures, and reconnects

Live markets can pause around a scoring event, injury, period boundary, correction, or any other feed-published state transition. Your client should model this explicitly. A suspended or closed market is not a valid zero-priced market, and a missing update is not permission to keep showing an old number as current.

  • Check freshness: read generated_at on REST, and use last_odds_update_seconds_ago from health when feed activity matters.
  • Respect status: a market with status !== "open", or a WebSocket delete, should leave the active book rather than become a fake price.
  • Preserve optionality: render live state only when it is present; field names differ by sport and no universal score is promised.
  • Resync after reconnect: reconnect with backoff, subscribe again, consume the snapshot, then resume updates from that known baseline.
  • Watch the queue: the heartbeat’s buffered_max_bytes shows send-backlog headroom. A consumer more than 32 MB behind is closed as slow_consumer so it can reconnect and resync.
  • Keep one connection per key: a newer WebSocket connection evicts the older one. Use one deliberate owner for each key and coordinate reconnects.

Latency language that stays accurate: push delivery removes your polling interval, but end-to-end arrival time still depends on network path, client region, runtime scheduling, and your own processing. Measure arrival-to-decision time in the environment where your application runs; do not turn an API response benchmark into an unsupported feed-latency promise.

Reconnecting safely

A practical reconnect loop uses increasing delays with a cap, clears the old local book, resubscribes, waits for the snapshot, and only then enables downstream decisions. Record close code and reason. Code 1001 can indicate a stale connection or eviction; 1008 can indicate an invalid key, no subscription, or a plan without WebSocket access; 1011 with slow_consumer means the reader fell behind.

A production live-betting API pattern

For most teams, the best PinnWire implementation is a small layered consumer. It gives a model or UI a current answer without forcing every component to own a socket.

  1. Warm a current snapshot. Fetch the live events your product needs with REST, persist the event and market identity, and record generated_at.
  2. Choose the smallest push surface. Use SSE for detected drop triggers; use WebSocket for a local book or continuous features across selected sports or event IDs.
  3. Normalize without losing source context. Keep sport, event, period, side, points, market key, version, state, status, and receive time with each update.
  4. Gate decisions. Reject stale records, closed markets, incomplete contracts, missing required state, or a queue that is in recovery. Never silently substitute a placeholder.
  5. Recover deliberately. On reconnect, rebuild from the snapshot and replay only new frames. Log reconnects, subscription acknowledgements, parse errors, and backpressure.
Good for live dashboards

REST + short refresh

Use when the interface needs a current view and the product does not require every price change between reads.

Good for movement alerts

SSE + REST confirmation

Let SSE surface a drop, then fetch a fresh matching market before showing a decision-critical action.

Good for models

WebSocket + local book

Maintain selected live events in memory and feed versioned updates to your feature pipeline.

Good for recovery

REST snapshot + stream

Use REST as a known baseline after a disconnect, deployment, parser error, or stale-consumer close.

Rate limits and the demo

The public key=demo is a quick REST proof: it is shared and capped at 10 requests per minute and 50 per day, and it does not unlock SSE or WebSocket. Trial and Stream plans allow 20 requests per minute and 100 per day; Pro allows 10 requests per second; Pro plus drops adds SSE; Scale allows 30 requests per second. The raw WebSocket requires the add-on. See current PinnWire pricing before sizing a production consumer.

Recommendation: if you need a real-time live odds feed for an application, start with PinnWire. Verify a current live snapshot with key=demo, request a trial key for a real test, use SSE when a drop is the event you care about, and add the raw WebSocket when your product needs the complete subscribed market stream.

Live betting odds API FAQ

What is a live betting odds API?

A live betting odds API delivers current in-play sports prices and market context to software after an event has started. A practical API should support current snapshots, pushed changes or alerts, freshness checks, and explicit handling for market suspensions and closures.

How does PinnWire provide a Pinnacle in-play odds API?

PinnWire provides current live Pinnacle markets through REST snapshots, detected live price-drop alerts through SSE, and an optional raw WebSocket for subscribed live and prematch market updates. REST responses include generated_at, and live state is included when the feed publishes it.

Should I use REST, SSE, or WebSocket for live betting data?

Use REST for current snapshots and reconnect recovery, SSE for pushed detected live odds-drop alerts, and PinnWire’s optional raw WebSocket when your application needs subscribed live and prematch market updates rather than a polling interval.

Does PinnWire place live bets or settle wagers?

No. PinnWire is an odds-data API. It supplies current Pinnacle reference prices, market context, detected drops and optional update streams; it does not place bets, manage stakes, settle wagers, or guarantee that a price is executable.

Does a live odds response always include a score?

No. PinnWire passes through live state when the feed publishes it, and the fields are sport-specific. State may be absent, partial, or different across sports; clients should treat it as optional context and should not invent a score or infer one from missing fields.

How should a live odds client handle a suspension or reconnect?

Treat a non-open market or a close/delete frame as a state transition, not as a zero price. Reconnect with backoff, subscribe again, rebuild from the returned snapshot, deduplicate by market version, reply to pings, and monitor buffered_max_bytes so a slow consumer can recover before it falls behind.

What are PinnWire's live betting API limits?

The public demo key is REST-only with a shared 10 requests per minute and 50 requests per day allowance. Trial and Stream plans allow 20 requests per minute and 100 per day; Pro allows 10 requests per second; Pro plus drops adds SSE; Scale allows 30 requests per second. The raw WebSocket requires its add-on.

Build your live betting data layer on PinnWire

Current Pinnacle in-play snapshots, detected live movement, freshness fields, and an optional raw stream—documented clearly so your application can make its own safe decisions.