Skip to content

BlogFundamentals

Webhooks vs polling for odds data

OddsRelay · · Updated · 4 min read

For odds data, polling beats webhooks. Prices change continuously, so there is no clean moment to push, and a poll that sends If-None-Match gets an empty 304 Not Modified when nothing has moved.

What is the difference between webhooks and polling?

Polling is your client asking the server for the current state on a schedule. A webhook is the server calling your client when something happens. Both move data between two systems. They suit opposite shapes of data.

  • Polling: your client makes a request on a schedule you choose and reads whatever the endpoint returns. You control the pace and retry on your own terms. The cost is requests that sometimes return nothing new.
  • Webhooks: you register a URL, and the provider sends an HTTP request to it when a defined event fires. You wait instead of asking. The cost is a public endpoint you must run and secure, plus retry and ordering logic for the deliveries that fail.

The deciding question is how the underlying data changes. Webhooks fit sparse, discrete events, such as a payment settling or a subscription being cancelled. Polling fits state that changes continuously and that you want a fresh snapshot of. Odds are the second kind.

Per-change pushes rebuild a stream

A bookmaker's price on a Premier League match can move many times before kick-off, and the exchange lay price it is paired with moves on its own. No single change in that is the moment that means "this changed, notify now" unless you invent a threshold. Push every change and you have rebuilt a stream. Push only the large moves and you miss the small ones that still matter to an oddsmatcher.

Polling avoids the question. You ask for the current board and get a coherent snapshot, every selection read from the same published version. With per-change webhooks you would stitch that picture back together yourself from partial updates, and handle the ones that arrive late or out of order.

ETag and 304 make polling cheap

The usual objection to polling is wasted requests. Conditional requests remove most of that cost. Every data reply carries an ETag header, a label of its content that changes when, and only when, the content changes. Store it and send it back on your next request as If-None-Match. If the board is unchanged, the reply is 304 Not Modified with an empty body, and you keep the rows you already hold. On OddsRelay a 304 costs no tokens. If the board changed, you get a 200, the new rows and a new ETag.

Polling the standard board with If-None-Match · example

GET /v2/odds/standard?region=uk&sports=soccer HTTP/1.1
Host: api.oddsrelay.io
Authorization: Bearer $ODDSRELAY_KEY
Accept-Encoding: gzip
If-None-Match: "b3d9a1f2-gz"

# unchanged since the last poll:
HTTP/1.1 304 Not Modified
ETag: "b3d9a1f2-gz"

# changed since the last poll (body shown decompressed):
HTTP/1.1 200 OK
ETag: "c7e04a88-gz"
{
  "meta": {
    "feed_type": "standard", "region": "uk", "odds_format": "decimal",
    "processed_at": "2026-09-20T12:18:11.402Z",
    "last_seen": { "william_hill": { "soccer": "2026-09-20T12:18:09Z" } },
    "count": 1,
    "version": "v2",
    "next_cursor": null
  },
  "data": [{
    "event_id": "or_evt_917dd44bce05",
    "sport_key": "soccer_epl",
    "sport_title": "Premier League",
    "commence_time": "2026-09-20T14:00:00Z",
    "home_team": "Arsenal",
    "away_team": "Chelsea",
    "markets": [{
      "key": "h2h",
      "outcomes": [{
        "name": "Arsenal",
        "back": [{ "bookmaker": "william_hill", "price": 2.9, "link": null }],
        "lay":  [{ "exchange": "betfair_exchange", "price": 3.0, "available": 175, "link": null }]
      }]
    }]
  }]
}

Each outcome carries back offers from bookmakers and lay offers from exchanges, with available giving the money on offer at the lay price. A 304 means every pair is as you left it, so nothing you compute from them needs redoing. The conditional requests guide has the exact rules, and the response envelope walks every field in a 200 body.

Does OddsRelay push webhooks?

No. OddsRelay is pull-only. There is no webhook, WebSocket or stream: you poll the board you want and read the current version. The feed covers 140+ bookmakers, 60+ of them live in the UK & Ireland, paired against Betfair, Smarkets, Matchbook and BETDAQ, and all of it is read with the same conditional GET.

Poll at the pace your product needs. To know how old the data in hand is, read meta.processed_at (the board's time, also sent as the X-Processed-At header) and meta.last_seen, the last read of each venue and sport. Now minus last_seen is an upper bound on a price's age. Every product on sale must meet a maximum update time of 10–20 s before it launches. The freshness guide covers both fields.

The case for push is strongest in-play, where prices move fastest. The feed has no in-play product: it is built for pre-match data. The live vs pre-match post explains where that line sits.

Where push does fit

For odds data the price stream itself is poll-shaped, but some adjacent signals are push-shaped:

SignalWebhook or poll?Why
Continuous price movesPollNo discrete event. A snapshot on request is the natural fit
A market opening or settlingWebhook-shapedSparse, discrete, worth acting on the moment it fires
A pair crossing a threshold you setPoll, filter client-sideOnly you know the threshold and your commission rate
A payment or account changeWebhook-shapedRare, and not part of the odds board

If you want alerts on top of a pull feed, poll the board and fire your own webhooks or notifications when a condition you care about is met. The threshold logic then lives in your product, where you can change it without asking a supplier, and the feed does one job: return the current board on demand.

Start polling

The quickstart makes one small call, prices it first with a free quote, then polls again with the ETag. Check which venues and sports are live on the coverage page, then request access for a key.