Documentation / Guides
Live odds
Best Betfair back and lay prices, when they arrive, how often they update, and what the numbers do and do not mean.
Every runner can carry a betfair block: the best available back and lay price
from the Betfair exchange, captured in the minutes before the race goes off.
"betfair": {
"selection_id": 84512233,
"back_price": 3.55,
"lay_price": 3.60,
"last_update": "2026-09-02T08:44:56Z"
}back_price is the best price you could have backed at; lay_price
is the best price you could have laid at. Both are decimal odds, and both are taken from the
top of the order book at the moment of capture.
When prices arrive
Capture starts about three minutes before the scheduled off and refreshes every few seconds until shortly before the traps open. Before that window a race has no prices at all — the exchange market exists, but there is rarely enough money in it for a price to mean anything.
The practical consequence: betfair is null on a race that is more
than a few minutes away, and populated on one that has just run. If you are polling a card in
the morning, expect nulls; poll again near the off.
How current they are
last_update is the moment that price was read from the exchange, not the moment
you called the API. Trust it over your own clock — it is the only honest measure of how
stale a number is:
# how old is this price, in seconds?
curl -s -H "X-API-Key: $KEY" \
https://api.greyhoundapi.com/v1/races/1541377233/market \
| jq '.data.runners[] | {dog: .dog_name, back: .betfair.back_price,
age_s: (now - (.betfair.last_update | fromdate))}'Prices reach this API within a second or two of being read, so a few seconds of age is normal and expected. A price several minutes old means the race has already run — that is the final capture before the off, which is usually the number people want.
The last price before the off
Once a race has run, back_price and lay_price hold the last values
captured, typically a handful of seconds before the traps opened. That makes them a useful
companion to the official starting price in sp: one is the bookmaker return, the
other is what the exchange was actually paying at the same moment. They frequently disagree,
and the difference is the interesting part.
What these numbers are not
- Not a full order book. You get the best price on each side, not the depth behind it, and not the size available at that price.
- Not a price history. Each capture overwrites the last, so you get the most recent price, not how it moved. If you need drift, poll and store your own series.
- Not a prediction. A short price reflects what other people are willing to bet, nothing more. This API reports market data; it does not rate runners, forecast results or suggest bets.
- Not guaranteed present. Coverage depends on a market existing and having prices during the capture window. Withdrawn runners carry no price at all.
Where to find them
The betfair block appears wherever a runner does — race cards, results,
and career form — so historical prices come back with the run they belong to. For a single
race, GET /v1/races/{race_id}/market returns every runner\'s prices together with
the exchange market id.
Always test for presence rather than assuming:
const bf = runner.betfair;
if (bf?.back_price) {
// a real price, captured at bf.last_update
} else {
// no market, outside the capture window, or a withdrawn runner
}