Horse racing and each-way odds data
In horse racing odds data, a race is an event with a course instead of two teams, every runner is an outcome, and each bookmaker's each-way price carries its own place terms.
Three of the matched boards are built around horse racing odds data: each-way, extra-place and best odds guaranteed (BOG).
Why racing data is harder than football
The field size and the place terms. A football match resolves to a home win, a draw and an away win, and that shape never changes. A race holds a variable number of runners, non-runners leave the field before the off, and each runner carries a win price plus an each-way settlement under terms the bookmaker sets for that race.
Those terms are two numbers: how many places are paid, and what fraction of the win odds the place part pays. One book can pay one-fifth the odds on three places while another pays one-quarter on the same race. Books quoting the same win price can settle the place part differently, so a model that hardcodes the terms is wrong on some races and never says so.
On top of that sit the racing concessions matched betting runs on. Best odds guaranteed (BOG) pays the starting price when it beats the price taken. Extra places, covered below, and BOG are both set bookmaker by bookmaker.
A race keys on course and off time
On the racing boards an event has sport_ set to horse_ and a venue field holding the course. There is no home_ or away_. commence_ is the scheduled off, and each runner is one entry in outcomes, by name. A race card is the events that share a course on the same day. Backing every runner in one race so any winner returns the same amount is dutching, the same arithmetic over a longer list of outcomes.
Treat event_ as the feed's own handle: opaque, the same on every board, and never changed once served, so it can key the race in your own records. To pull racing alone, the matched boards take sports= and a kick-off window, both covered in the matched-board filters guide.
Each-way and extra-place odds data explained
Each-way and extra-place odds data carry each bookmaker's place terms and two exchange lays, one on the win market and one on a place market. An each-way bet is two bets, staked as two equal parts. The win part pays only if the runner wins, and it is laid on the exchange's win market. The place part pays if the runner finishes in one of the paying places, at a fraction of the win odds, and it is laid on an exchange place market, which settles on its own number of places.
What is an extra-place offer?
An extra-place offer is a bookmaker paying each-way place terms on more places than a race's standard terms, five where four is usual, say. The exchange's place market still settles on the usual number, and that gap is what the extra-place board finds. If the runner finishes in one of the extra places, the bookmaker's place part wins and the place lay wins too, because the exchange market did not pay that position. Any other finish settles like an ordinary each-way qualifying bet, and the extra-place entry works one through with stakes.
The extra-place board has the each-way board's shape, so code written for one reads the other.
Place terms travel on each back offer
On the each-way and extra-place boards every back offer carries places, the number of places that bookmaker pays, and place_, its place terms as a decimal (0.2 is one-fifth, 0.25 one-quarter). The lay side splits into win and place arrays, because the exchange runs them as separate markets, and every place lay carries its own places: the number the exchange's place market settles on.
{
"meta": {
"feed_type": "each-way", "region": "uk",
"odds_format": "decimal",
"processed_at": "2026-09-19T12:41:07.312Z",
"last_seen": {
"paddy_power": { "horse_racing": "2026-09-19T12:41:05Z" },
"fitzdares": { "horse_racing": "2026-09-19T12:41:04Z" }
},
"count": 1,
"version": "v2",
"next_cursor": null
},
"data": [{
"event_id": "or_evt_4c19a07be2d3",
"sport_key": "horse_racing",
"sport_title": "Horse Racing",
"commence_time": "2026-09-19T13:50:00Z",
"venue": "Newmarket",
"markets": [{
"key": "each_way",
"outcomes": [{
"name": "Harbour Lights",
"back": [
{ "bookmaker": "paddy_power", "price": 9.5, "places": 3, "place_fraction": 0.2, "link": null },
{ "bookmaker": "fitzdares", "price": 9.0, "places": 3, "place_fraction": 0.25, "link": null }
],
"lay": {
"win": [{ "exchange": "smarkets", "price": 10.0, "available": 48.2, "link": null }],
"place": [{ "exchange": "smarkets", "price": 2.9, "available": 63.5, "places": 3, "link": null }]
}
}]
}]
}]
}The best win price is not the best each-way bet. The place part's price is 1 + (win − 1) × place_, so the Paddy Power offer's place part is 2.7 while the Fitzdares offer's, at one-quarter, is 3.0. Against a place lay at 2.9, one of those place parts beats the lay and the other does not. The terms have to be read per offer, every time.
The lay side comes from Betfair, Smarkets and Matchbook, and a pair appears only where the exchange side has liquidity behind it. lay.win and lay.place each list offers lowest price first, and the two can come from different exchanges. One outcome's lay.place can hold place markets with different place counts, so pick the place lay by places: on each-way, the market whose places equals the offer's, and on extra place, one with fewer.
Rating a pair and working out its qualifying loss happen on your side, at your commission rate. Each part is sized like a standard lay: the win part against the win lay at the win price, and the place part against the place lay at the place part's price. The each-way calculator and the extra-place calculator take one row's terms and both lay prices and show the result on every finish.
// Your code, per back offer on an each-way or extra-place outcome const placePart = 1 + (offer.price - 1) * offer.place_fraction; // lay.place is lowest price first: take the first one with the right place count const placeLay = board === "each-way" ? outcome.lay.place.find((l) => l.places === offer.places) // the bookmaker's own count : outcome.lay.place.find((l) => l.places < offer.places); // extra place: fewer places if (!placeLay) return; // no place lay with that count: skip this offer const extraPlaces = offer.places - placeLay.places; // above 0: the book pays places the exchange does not
Raw has carried each-way terms too since 4 November 2026, on winner markets sold each-way (outright_) in horse racing, greyhound racing and golf. They sit on the venue's market as places, place_ and extra_, which is true when the venue pays more places than its standard terms for the event. Any other set of terms a bookmaker offers for the same event is a market of its own, outright_. Raw leaves the pairing to you, and the each-way and extra-place boards stay horse racing only.
Each-way, Extra place and Best odds guaranteed side by side
| Board | What it pairs | What to compare |
|---|---|---|
| Each-way | Each bookmaker's win price and terms against the exchange win and place lays | A place part priced close to, or above, the place lay |
| Extra place | The same shape as each-way | How many places the bookmaker adds: back[].places minus lay.place[].places |
| Best odds guaranteed | A win market: bookmaker back prices against exchange lays | The back price against the lay |
BOG has the standard board's shape, with no place terms and a flat lay array. The starting price itself is not in the feed: it is set at the off, after the pre-match prices the feed carries, so a tool plans on the back and lay prices and the bookmaker pays any uplift later under its own terms. A tipster proofing record meets the same gap: it stores the price on offer when a selection goes out and takes the starting price from a results source.
The racing boards are on every plan. Offer rules such as qualifying races and maximum stakes stay with each bookmaker, and the feed carries prices and terms, never eligibility. The each-way term in the glossary covers the bet itself for anyone new to it. The 2Up board, a football board, sits in this category too, and 2Up odds data walks through one of its replies.
Price age is yours to check near the off
Racing markets often move most in the last minutes before a race, then the pre-match prices end at the off. The feed carries a race's prices up to its start, and none in running.
Freshness is something you read from the reply. meta.processed_ is the board's time, and meta.last_ gives each venue's last read per sport, so now minus last_ is an upper bound on that bookmaker's racing price age. Every product on sale meets a maximum update time of 10–20 s for match odds, and for every market within six hours of kick-off. Further from kick-off, prices in the other markets can be older. The freshness guide covers both fields.
An unchanged board costs nothing to poll
Every data reply carries an ETag. Send it back as If-None-Match on your next poll, and a reply that has not changed comes back as a 304 that costs no tokens. The horse racing API tutorial in Python uses it to post a race's prices to Discord or Telegram only when they change.
A format= reply is the events alone, so its ETag moves only when your events do, and a new board version that leaves them unchanged is still a 304. The default envelope carries meta.processed_, so its ETag moves with every new board version. Near the off most new board versions change some runner's price, so expect most calls there to be 200s at the board's full token cost, whichever form you ask for.
A bare reply moves the board's time to the X-Processed-At header and leaves out meta.last_: read the same times from the keyed / call, which costs no tokens. The racing boards cost the same whatever you filter, so on bare a filter only makes a 304 likelier. The conditional requests guide shows the request loop.
Start with one race
The coverage page lists the bookmakers the feed covers for racing. Pick one meeting and walk its each-way outcomes through the arithmetic above.
Sources, checked 29 September 2026
Related posts
- How to calculate qualifying loss and ratingsThe rating and qualifying loss formulas, worked on one back and lay pair at your own commission.
- Best odds guaranteed (BOG) and your dataBOG pays the starting price when it beats the price you took. What that changes in a matched bet.
- Why lay liquidity matters in a matched odds feedA lay price with no money behind it cannot be taken. How to check a pair against your stake.
18+ · OddsRelay supplies odds data only and takes no bets. Please gamble responsibly.