Subscribe once to the markets you care about. Every price move arrives as it happens — a burst while the game moves, silence when it doesn't. Silence is normal, not an outage.
| Push WebSocket | Polling loop | |
|---|---|---|
| When updates arrive | The moment the book moves | On your next request cycle |
| Wasted requests | None — no move, no message | Most polls see no change |
| Cost to scale frequency | Zero — pushes don't consume quota | More polls = more requests = more spend |
| Market status | OPEN ↔ SUSPENDED flips pushed live | You infer it from diffs |
| Live & pre-match | One subscription, both | Two schedules to babysit |
The live transport is AWS AppSync GraphQL over WebSocket — the same transport class the FanDuel Sportsbook app itself uses. You subscribe with a GraphQL subscription carrying the market IDs you picked during REST discovery:
subscription OnUpdateMarketPrice($ids: [String!]!) {
onUpdateMarketPrice(ids: $ids) {
id
marketStatus
runnerDetails {
selectionId
handicap
runnerStatus
winRunnerOdds {
americanDisplayOdds { americanOdds americanOddsInt }
decimalDisplayOdds { decimalOdds }
}
}
}
}
Chunk your IDs — roughly 30 markets per subscription works well; 90 markets across three subscriptions ack cleanly. Larger single subscriptions hit the message-size cap. Measured on a live reference run: 90 markets over 75 seconds produced 13 price updates with a median 0.35 s gap between ticks inside a burst.
Every update carries the market status, the runner identity, and both odds formats side by side:
| Field | Meaning |
|---|---|
marketStatus | OPEN or SUSPENDED — pushed the moment it flips. |
selectionId | Stable ID for the runner you are pricing. |
handicap | The spread/total line attached to the runner. |
runnerStatus | Status of the individual runner. |
americanOdds / americanOddsInt | American display odds (string and integer forms). |
decimalOdds | Decimal display odds. |
The public demo snapshot exposes the same board the WebSocket subscription watches — live and pre-match totals, per-sport breakdown, and a tape of the latest price moves:
curl https://fanlinewire.com/odds.json
Fetch it twice a minute apart and compare: the sequence counter climbs with every collector tick, the fixtures tape reorders, and the drops list records every move against the bettor. That is the subscription's view of the board, at snapshot pace.
Yes — the live feed is an AWS AppSync GraphQL WebSocket. You subscribe once per ~30-market chunk and price updates are pushed to you as they happen. REST discovery handles the one-time market-ID lookup.
Three reasons: latency (the tick arrives when the book moves, not on your next cycle), waste (a quiet market costs nothing — a poll costs a request), and signal (OPEN ↔ SUSPENDED flips arrive as events, so you can alert on them).
Subscribe in chunks of roughly 30 markets — 90 across three subscriptions acks cleanly. Bigger single subscriptions hit AppSync's message-size cap. There is no practical cap on the number of chunks.
A push socket goes quiet when nothing is moving. That is healthy. Judge feed health by your subscription acks and market-status flips — never by tick count. During live action you get bursts; measured median gap inside a burst is 0.35 s on the reference run.
No. Push streams ride flat-rate plans — the message rate can't change your bill. That is the structural difference vs credit-priced polling APIs.