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
Shrink Every Response First
Before you tune polling intervals, make each response smaller.market_ids: biggest control for response sizeaffiliate_ids: only request the books you actually surfacemain_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.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.
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.
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.
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 whoseclosed_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.
Recommended Polling Intervals
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_attimestamp 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
400cursor 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.
- On one cursor error, fetch one fresh full snapshot from the events endpoint
- On known zero-delay access, extract its valid
delta_last_idand resume polling - 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-DatapointsX-Datapoints-UsedX-Datapoints-RemainingX-Datapoints-ResetX-Rate-Limit
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.