Webhooks and stream

FanDuel webhooks and live stream

FanDuel line and price changes pushed as they happen: a Server-Sent Events stream with resume on every plan, and signed webhooks on Production and up.

FanDuel API is an independent data service operated by FF API Inc. It is not affiliated with, endorsed by or sponsored by FanDuel.

Stop polling: take each change the moment it is collected, on a connection or at your URL.

Stream
Server-Sent Events with Last-Event-ID resume. Free sees it five minutes behind; concurrent connections scale with the plan.
Webhooks
HMAC-signed POSTs with retries and a delivery log, up to five endpoints, on plans that list Webhooks.
Same frames
Stream events, webhook bodies and change feed rows carry the same fields and cursors.

What it returns now

Real rows, 5 min delay, as of 3:25 PM ET

GET /api/v1/stream, as the frames arrive
id: 36350
event: change
data: {"cursor":"36350","kind":"line_move","league":"NCAAF","player":"Antonio Jordan","stat":"receiving_yards","previous":{"line":34.5,"over_american":-114},"current":{"line":30.5,"over_american":-114},"at":"2026-11-06T20:24:13.461Z"}

id: 36311
event: change
data: {"cursor":"36311","kind":"line_move","league":"NBA","player":"Payton Pritchard","stat":"pra","previous":{"line":19.5,"over_american":-128},"current":{"line":20.5,"over_american":-102},"at":"2026-11-06T20:23:58.749Z"}

id: 36310
event: change
data: {"cursor":"36310","kind":"line_move","league":"NBA","player":"Neemias Queta","stat":"pra","previous":{"line":18.5,"over_american":100},"current":{"line":17.5,"over_american":-128},"at":"2026-11-06T20:23:58.749Z"}

Endpoints and parameters

GET/api/v1/stream

Line, price and status changes pushed as they happen, with Last-Event-ID resume. Free is delayed 5 minutes; concurrent connections are capped per plan.

ParameterInDescription
leaguequeryLeague code as FanDuel lists it, such as NBA.
GET/api/v1/webhooks

Your registered webhook endpoints. Production and up.

POST/api/v1/webhooks

Register an HTTPS endpoint for signed change events; the signing secret is shown once. Production and up, up to five endpoints.

Code

curl
curl "https://fanduelapi.com/api/v1/stream?league=NBA" \
  -H "Authorization: Bearer $FANDUEL_API_KEY"
Python: verify a webhook
import hmac, hashlib, time

# X-Webhook-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.raw_body">
def verified(raw_body: bytes, header: str, secret: str, tolerance=300) -> bool:
    parts = dict(item.split("=", 1) for item in header.split(","))
    t = int(parts["t"])
    if abs(time.time() - t) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

Keys look like fd_.... Keep one in the FANDUEL_API_KEY environment variable on your server, never in browser code. Every response's meta says which plan answered, how far behind it is and how fresh the collection is.

Which plans include it

  • FreeStream, 5 minutes behind; no webhooks
  • DeveloperStream; webhooks from Production
  • ProductionStream and signed webhooks
  • ScaleStream and signed webhooks

Read from the plans on the pricing page. Every request counts against the monthly and per-minute allowance; request quotas explains how.

Works well with

Make your first call in a few minutes

Sign up, create a key in the dashboard, and send it as a Bearer token. The free plan needs no card and reads the same data five minutes behind.

Get a free API key