How to get bookmaker odds data into your app
How to get bookmaker odds data into your app comes down to two routes: collect the prices yourself, or license a feed and call it over HTTP.
Unless collecting odds is the product you sell, license the feed.
Decide these first
Settle four things first.
- Which bookmakers. List the books your users expect to see, and check each one against a supplier's coverage page before anything else.
- Which region. Bookmakers publish different prices, and sometimes different markets, per country. OddsRelay serves the UK & Ireland. If your product is built for bettors elsewhere, this feed is the wrong fit.
- Raw or matched. Raw is each bookmaker's price on its own, which suits comparison tables and content. Matched pairs each bookmaker price with an exchange lay price for the same outcome, which is what an oddsmatcher or a matched-betting tool needs.
- Pre-match or in-play. The OddsRelay feed serves pre-match prices by default and, since 2 November 2026, in-play prices with
inPlayon raw and on the standard and dutching boards. Those are polled like the rest, with no scores or match clock, and bet365 and William Hill carry none. Live vs pre-match odds data sets out the difference.
If these terms are new, what an odds API is sets the baseline. The anatomy of an odds API response walks a real reply field by field.
A first call to a feed
Four steps, all plain HTTP: get a key, make one authenticated GET, parse the JSON, then cache it. With OddsRelay the key goes in an Authorization: Bearer header (or x-api-key), and each matched board has its own path under /.
curl --compressed -H "Authorization: Bearer $ODDSRELAY_KEY" \ "https://api.oddsrelay.io/v2/odds/standard?region=uk&sports=soccer"
Keep --compressed on: it asks for gzip, and without it the reply is a much larger plain body. Add quote= to any data request and it returns the call's price in tokens instead of the data, for free. The filters and tokens guide explains how a live-feed price comes from the board and filters you ask for, never from the size of the reply.
The reply is an envelope. meta describes the board as a whole, and data holds events, each with its markets and outcomes. On the standard board, every outcome carries back offers, the bookmakers' prices, and lay offers, the exchanges' prices with available, the money on offer at that price. One event, trimmed to one outcome:
{
"meta": {
"feed_type": "standard", "region": "uk",
"odds_format": "decimal",
"processed_at": "2026-09-17T02:20:57.271Z",
"last_seen": { "william_hill": { "soccer": "2026-09-17T02:20:55Z" } },
"count": 26,
"version": "v2",
"next_cursor": null
},
"data": [{
"event_id": "or_evt_917dd44bce05",
"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": "smarkets", "price": 3.0, "available": 175, "link": null }]
}]
}]
}]
}Each back price is paired with exchange lay from Betfair, Smarkets and Matchbook, and only where that lay has money behind it. The response carries prices only, and anything computed from them is yours. The API reference documents each field.
Cache with ETags and poll
The feed is pull-only: your app asks, the feed answers. Every data reply carries an ETag. Send it back as If-None-Match on the next call, and an unchanged board comes back as a 304 with no body, which costs no tokens.
- Make the first call. Store the body and its
ETag. - On each later call, send
If-None-Matchwith that value. A304means the copy you hold is still the current board. - On a
200, replace your copy and store the newETag.
Judge freshness from the timestamps in the reply, never from when you fetched it. meta.processed_ is the board's time. meta.last_ is when each venue and sport was last read, so now minus that time is an upper bound on a price's age. Show it to your users, or act on it, rather than assuming. The freshness guide and the conditional requests guide cover both in detail.
When to collect the data yourself
Build it when the data is your product, or when you need books or markets no supplier carries.
Reading a price once is the small part of the job. The lasting cost is keeping every bookmaker working as each one changes, then naming the same event the same way across books so their prices line up. A matched product adds a second system on top: pairing each back price with an exchange lay price and deciding when there is enough money behind the lay to show it.
A licensed feed moves that upkeep to the supplier. OddsRelay covers 140+ bookmakers, 60+ of them live in the UK & Ireland, bet365 included on every plan. Whichever supplier you pick, check the coverage before you commit: the coverage page lists every venue and the sports it carries on each feed. We work the costs through in buy versus build.
Make your first call
A key and the quickstart get you to a first priced call.
If your app shows those prices to other people, it runs on Enterprise, and a Free key of your own is enough to try it first.
Related posts
- What is an odds API?An odds API returns bookmakers' prices as JSON. What a response holds, and raw versus matched data.
- The anatomy of an odds API responseEvery field in a /v2 odds response, from the meta envelope down to each back and lay offer.
- Buying vs building an odds data layerThe five jobs inside an odds data layer, and which ones a licensed feed takes off your team.
18+ · OddsRelay supplies odds data only and takes no bets. Please gamble responsibly.