FanLine Wire API documentation

Push access to live & in-play and pre-match FanDuel Sportsbook odds — moneyline, spread and totals markets — over an AWS AppSync GraphQL WebSocket, with a REST endpoint for market discovery.

Overview

FanLine Wire serves real-time odds from FanDuel Sportsbook, a US sportsbook. The feed covers moneyline, spread (point spread) and totals (over/under) markets, both live/in-play and pre-match.

Every price carries American and decimal odds side by side — pick whichever your stack wants, they arrive together.

Runner-level detail travels with each price: selectionId, handicap and runner status.

Quickstart

Copy-paste, run, done — the public demo snapshot needs no key:

import json, urllib.request

snap = json.load(urllib.request.urlopen("https://fanlinewire.com/odds.json"))
print(snap["generated_at"], "|", snap["live"]["total"], "live /", snap["prematch"]["total"], "prematch")

for row in snap["fixtures"][:3]:
    prices = ", ".join(str(p["american"]) for p in row["prices"])
    print(f'{row["sport"]:12} {row["fixture"]:40} {row["status"]:10} {prices}')

That prints the snapshot timestamp, live/prematch market totals, and the first rows of the recent-tick tape. Fields are documented in Payload fields and in llms.txt. Snapshot cadence: poll no faster than every 10 seconds — for true pushes use the live WebSocket.

Transport

Two transports, two jobs:

Live prices   AWS AppSync GraphQL over WebSocket (push)
Discovery     REST endpoint (market discovery)

The WebSocket is push-based and event-driven: you subscribe once to the markets you care about, and updates arrive when the book moves — nothing arrives when it doesn't. There is no polling loop to babysit.

REST market discovery

Before you can subscribe, you need market IDs. The REST endpoint lists available events and markets — query it, pick your markets, then hand the IDs to the live subscription.

# discovery — list markets (shape shown at launch)
GET /markets?region=nj

Exact paths, parameters and response schemas are documented here when the public endpoint opens. The transport facts above are final; endpoint naming is the only thing still moving.

Live WebSocket subscription

Subscribe with a GraphQL subscription carrying the market IDs you chose during 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.

Markets

MarketNotes
MoneylineWho wins. Two-way for most events.
Spread (point spread)Carries a handicap per runner.
Totals (over/under)Over and under sides of the line.

That is the full market list today. Props, alternates and specials are not in the feed and are not promised anywhere on this site.

Payload fields

Each price update carries:

FieldMeaning
marketStatusOPEN or SUSPENDED — see Market status.
selectionIdStable ID for the runner you are pricing.
handicapThe spread/total line attached to the runner.
runnerStatusStatus of the individual runner.
americanOdds / americanOddsIntAmerican display odds (string and integer forms).
decimalOddsDecimal display odds.

Market status

marketStatus flips OPEN ↔ SUSPENDED in real time, and that flip is genuinely useful signal: a suspension typically means the book has pulled the market — a review, a big play, a line reset — and a reopen means prices are trusted again.

Build status changes into your own alerting; clients that treat "quiet" as "healthy" miss exactly these moments.

Update pace

Updates are event-driven. During live action a burst of ticks arrives together; when nothing is happening, the socket stays quiet. Quiet is normal.

Measured on a live reference run: 90 markets over 75 seconds produced 13 price updates, with a median gap of 0.35 s between ticks inside a burst. Judge feed health by your subscription acks and status flips — never by tick count alone.

Regions

The feed is US-region data, scoped by state slug — nj, ny and pa today. Ask per region; coverage follows the source.

The feed's scope is the full FanDuel Sportsbook. A sport-by-sport list will be published here when the rollout across the full board is complete.