Skip to main content
Polling the full events endpoint every few seconds is expensive, burns data points, and can trip your per-second throttle if you scale it across many sports or books. This guide covers how to keep data fresh without paying for or requesting far more than you need.

Why Polling Efficiency Matters

TheRundown usage is not just about request count. The cost of a polling loop depends on:
  • how many sportsbooks you request
  • how many markets you include
  • whether you pull full event payloads or only deltas
  • how often you refresh
A naive loop that fetches full event snapshots every few seconds can waste both data points and burst budget. Delta endpoints solve this by returning only what changed since your last request.

Shrink Every Response First

Before you tune polling intervals, make each response smaller.
Use these levers aggressively:
  • market_ids: biggest control for response size
  • affiliate_ids: only request the books you actually surface
  • main_line=true: skip alternate lines if your product only shows the primary market
  • event-specific endpoints: if you only care about a handful of games, do not fetch the full slate
  • hide_closed_markets=1: useful during market discovery to avoid off-board clutter

Delta Endpoint Bootstrap Flow

The pattern for using delta endpoints has three stages:

1. Fetch the full snapshot

Start by loading the complete event data for the sport and date you need. This gives you the initial state and the first delta cursor.
For a plan with explicitly confirmed zero data delay, the response body’s meta.delta_last_id is the canonical bootstrap cursor for /api/v2/markets/delta. Accept a positive integer whether encoded as a number or string. Never replace a missing or invalid cursor with 0.
Delayed plans use narrow, repeated event snapshots and never bootstrap market-delta polling from a delayed snapshot. A missing or invalid X-Data-Delay-Seconds header means the delay is unknown, not zero. Use delta polling only when a known plan entitlement establishes zero delay; a positive server-reported delay always rules out delta polling.

2. Poll the market delta endpoint

On each subsequent poll, pass your saved cursor to /api/v2/markets/delta. It returns only the prices that changed since that cursor — the most efficient way to keep odds fresh. Use the same explicit full-game core scope in the snapshot and delta request: 1,2,3,41,42,43. Market delta filters IDs literally, and delta rows retain their actual market IDs. For soccer, NHL regulation-time, tennis, and futures scopes, use the sport-aware recommended core market scopes.
Each response includes its own meta.delta_last_id (also an integer) — use that as last_id on the next poll. Do not bootstrap with last_id=0: a cursor that has fallen too far behind the current head is rejected, so always seed from a fresh, zero-delay events snapshot.
The two delta endpoints take different, non-interchangeable cursors:
  • /api/v2/markets/delta (price changes) uses an integer cursor. On known zero-delay access, bootstrap it from the events snapshot’s integer meta.delta_last_id, then follow the integer cursor in each markets-delta response. This is the endpoint for odds polling.
  • /api/v2/delta (full event-object changes: status, scores, the whole event) uses an ordered UUID cursor, e.g. 11f1-23b3-f4d42784-8057-a3a997572248. That cursor is only returned by /api/v2/delta’s own responses — the events snapshot does not provide it.
Passing the integer events cursor to /api/v2/delta returns a 400. For price and odds polling, use /api/v2/markets/delta.

3. Merge updates into local state

Each delta response contains changed price rows. Upsert each row by its exact event, market, participant, participant type, normalized line, and affiliate identity; remove rows whose closed_at is present; and retain the returned is_main_line value. Update your cursor to the new delta_last_id from the response. Market delta is scoped by sport, not date. Ignore a delta row whose event_id is absent from your latest snapshot, and use the next snapshot to refresh event membership and schedule metadata.
Polling futures too? The futures snapshot (GET /api/v2/sports/{sportID}/futures) provides the same meta.delta_last_id bootstrap cursor, but futures market IDs are not in the delta feed’s default set — pass them explicitly (e.g. market_ids=1141). See the Futures guide.

Choosing Between Event and Market Delta

The market delta is usually the cheapest option because it returns only the specific prices that changed, rather than the entire event object. The cursors are not interchangeable — the integer from the events snapshot bootstraps markets/delta only, and /api/v2/delta rejects it with a 400. Match your polling frequency to your use case. Faster polling uses more data points and increases the chance of hitting your burst limit if you parallelize heavily.
On a WebSocket-enabled tier, use the WebSocket endpoint instead of polling when you need sub-second odds updates across every book or play and game-stat updates at play latency. For supported live games, live data trails the on-field action by roughly 15–20 seconds, in line with the typical broadcast delay. WebSocket traffic does not increment the HTTP request counter, but pushed messages are still metered as data points.

Cache TTL Recommendations

Not all data changes at the same rate. Cache aggressively for reference data and use shorter TTLs for live data.

Staleness Guards

Your delta cursor can become stale if you stop polling for an extended period. When this happens, the delta endpoint may return an error or skip events that changed while you were away. How to detect stale data:
  • Track the updated_at timestamp on your cached events. If the newest update is more than 5 minutes old during a live game window, your data may be stale.
  • An empty delta response can mean that no matching prices changed; it does not by itself indicate a stale cursor.
  • A 400 cursor error can require one fresh snapshot bootstrap on known zero-delay access. Stop on authentication, entitlement, or rate-limit responses and handle them through your scheduler or account flow.
How to recover:
  1. On one cursor error, fetch one fresh full snapshot from the events endpoint
  2. On known zero-delay access, extract its valid delta_last_id and resume polling
  3. If the next delta response still has a cursor error, stop and investigate; do not loop re-bootstrap requests

Watch Your Usage Headers

Every production poller should log and monitor:
  • X-Datapoints
  • X-Datapoints-Used
  • X-Datapoints-Remaining
  • X-Datapoints-Reset
  • X-Rate-Limit
That gives you the feedback loop to tune filters and polling intervals before users start hitting limits.

Code Example: Python Polling Loop

This bounded example uses market delta only when a known entitlement establishes zero delay. Delayed or unknown access repeats narrow snapshots instead. It is intentionally finite so callers can apply their own scheduler, retry policy, and alerting.

WebSocket vs. Polling Decision Guide

Many production applications use both: WebSocket for live windows, with delta polling as a fallback when the socket disconnects or for lower-tier keys that do not have WebSocket access. See the Building an Odds Screen guide for this pattern in practice.