API reference / Racing
GET /v1/racing/toteNorth American tote odds (TVG): live win odds and morning line
TVG's live tote odds for every US and Canadian race on its board: per betting interest the morning line and the current win odds, both odds-to-1 and as a decimal price, with the WIN pool behind them. Read every 30 seconds while a race is open, and once more when it is official, so a race of the day keeps the odds it settled on (`final`). **A tote, not a bookmaker.** These are pari-mutuel odds: the payoff is whatever the pool pays when it closes, so a pre-race `win_odds` is an estimate, and a US payoff is rounded down to a dime per $2 (minimum $2.10). The settled payoffs are on /v1/racing/results (`country=US`, product US-TOTE). Nothing here enters a bookmaker list. **Before the pools open** a track's displayed odds simply repeat the morning line, so `win_odds` is null until the WIN pool holds money (`pools_open`), and it stays null on a scratched runner. **Every race, priced or not.** The Australian books price a small share of the North American card. `race_id` names the priced race where there is one (the same race carries this block as `tote` on /v1/racing/next-to-go); it is null otherwise. **How the odds moved (`history=true`).** For one race (`race_id` or `source_race_id`), every read in which its win odds or WIN pool changed, from an hour before post until it is official, oldest first — late money on a US tote shows up here, as does a race going off after its post time (`secs_to_post` negative). Kept from 2026-10-27. **Exotics (`exotics=true`).** For one race, the probables (what each exacta, quinella or daily double combination would pay for the pool's minimum stake right now) and the will-pays of multi-race pools, read from 20 minutes before post. The race's surface, track condition, exotic pool sizes and scratching reasons are in every `tote` block.
X-API-Key
2 credits
curl 'https://api.puntersedge.online/v1/racing/tote' \
-H 'X-API-Key: YOUR_KEY'
| Name | In | Type | Required | Description |
|---|---|---|---|---|
date |
query | string | no | US Eastern race date, YYYY-MM-DD. Defaults to today's US card. Any day from `coverage_from` to tomorrow; outside that is a free 422. |
country |
query | string | no | US, CA or US,CA (the default). |
status |
query | string | no | open, off or official. Omit for every race of the day. |
race_id |
query | string | no | One priced race, by the race_id next-to-go serves. |
source_race_id |
query | string | no | One race by TVG's key (tvg_<track>_<date>_<n>), priced or not. Its date is the default `date`. |
history |
query | boolean | no | true adds each race's `history`: how its odds and WIN pool moved from an hour before post. Needs one race (race_id or source_race_id); without one it is a free 422. |
exotics |
query | boolean | no | true adds each race's `exotics`: the probables (exacta, daily double...) and will-pays from the last read. Needs one race (race_id or source_race_id); without one it is a free 422. |
Status codes: 200, 401, 402, 422, 429, 500. Response bodies are JSON; the full schema is in /openapi.json.
200 application/json
— this call costs 2 credits.
Field names and types are as the API returns them; values are a real sample, trimmed to a few items.
{
"date": "2026-10-26",
"source": "tvg",
"coverage_from": "2026-10-27",
"races": [
{
"exotics": {
"read_at": "2026-10-26T20:18:03Z",
"probables": [
{
"code": "DB",
"name": "Daily Double",
"min_wager": 1.0,
"combos": [
[
2,
1,
19.8
],
[
2,
2,
40.3
],
[
2,
3,
86.2
],
[
2,
4,
14.7
]
]
},
{
"code": "EX",
"name": "Exacta",
"min_wager": 1.0,
"combos": [
[
2,
3,
32.8
],
[
2,
4,
6.0
],
[
2,
5,
22.5
],
[
2,
6,
26.8
]
]
}
],
"will_pays": [
{
"code": "DB",
"name": "Daily Double",
"stake": 2.0,
"legs_won": [
4
],
"payouts": [
[
2,
102.4
],
[
3,
294.4
],
[
4,
19.4
]
]
}
]
},
"source_race_id": "tvg_PHI_2026-10-26_8",
"race_id": "969e0778-2659-4289-bede-d2caf414fee4",
"venue": "Parx Racing",
"track_code": "PHI",
"country": "US",
"category": "horse",
"race_number": 8,
"race_date": "2026-10-26",
"post_time": "2026-10-26T20:08:22Z",
"tote": {
"source": "tvg",
"product": "US-TOTE",
"currency": "USD",
"status": "official",
"pools_open": true,
"final": true,
"win_pool": 23296.0,
"read_at": "2026-10-26T20:18:03Z",
"surface": "Dirt",
"surface_changed_from": null,
"track_condition": "Fast",
"condition_changed_at": null,
"pools": [
{
"code": "DB",
"name": "Daily Double",
"amount": 24096.0
},
{
"code": "EX",
"name": "Exacta",
"amount": 28437.0
},
{
"code": "PL",
"name": "Place",
"amount": 16836.0
},
{
"code": "SH",
"name": "Show",
"amount": 30582.0
},
{
"code": "SU",
"name": "Superfecta",
"amount": 0.0
},
{
"code": "TR",
"name": "Trifecta",
"amount": 23244.16
},
{
"code": "WN",
"name": "Win",
"amount": 23296.0
}
],
"race_class": "Allowance Optional Claiming",
"conditions": "(PLUS UP TO 40% PABF) FOR FILLIES AND MARES THREE YEARS OLD AND UPWARD WHICH HAVE NEVER WON TWO RACES OTHER THAN MAIDEN, CLAIMING, STARTER, OR STATE BRED OR WHICH HAVE NEVER WON FOUR RACES OR CLAIMING PRICE $50,000. Three Year Olds, 122 lbs.; Older, 125lbs. Non-winners Of A Race Since September 26 Allowed 3 lbs. Claiming Price $50,000 (Races Where Entered For $16,000 Or Less Not Considered In Allowances).",
"purse": 52000.0,
"purse_currency": "USD",
"claiming_price": null,
"age_restriction": "3U",
"runners": [
{
"number": 1,
"name": "Carousel Queen",
"scratched": true,
"favorite": false,
"morning_line": "8/1",
"morning_line_decimal": 9.0,
"win_odds": null,
"win_decimal": null,
"win_pool": 0.0,
"scratch_reason": "Veterinarian",
"scratched_at": "2026-10-26T14:10:19.033000Z",
"jockey": "Castillo Angel",
"trainer": "Lake Scott A",
"sex": "F",
"sire": "Uptowncharlybrown",
"dam": "La Padrina",
"dam_sire": "El Padrino",
"medication": "L",
"weight_lb": 122,
"age": 4
},
{
"number": 2,
"name": "Volleyballprincess",
"scratched": false,
"favorite": false,
"morning_line": "5/1",
"morning_line_decimal": 6.0,
"win_odds": "5/2",
"win_decimal": 3.5,
"win_pool": 5334.0,
"scratch_reason": null,
"scratched_at": null,
"jockey": "Lopez Paco",
"trainer": "Linder, Jr. Louis C",
"sex": "F",
"sire": "Mo Town",
"dam": "Prom Dress",
"dam_sire": "Stephen Got Even",
"medication": "L",
"weight_lb": 122,
"age": 4
},
{
"number": 4,
"name": "More Than Grace",
"scratched": false,
"favorite": true,
"morning_line": "4/5",
"morning_line_decimal": 1.8,
"win_odds": "1/5",
"win_decimal": 1.2,
"win_pool": 13929.0,
"scratch_reason": null,
"scratched_at": null,
"jockey": "Sanchez Mychel J",
"trainer": "Pino Michael V",
"sex": "F",
"sire": "More Than Ready",
"dam": "Trace Of Grace",
"dam_sire": "Petionville",
"medication": "L",
"weight_lb": 125,
"age": 4
}
]
},
"history": [
{
"read_at": "2026-10-26T20:18:03Z",
"secs_to_post": -581,
"status": "official",
"final": true,
"win_pool": 23296.0,
"runners": [
{
"number": 2,
"win_odds": "5/2",
"win_decimal": 3.5,
"win_pool": 5334.0
},
{
"number": 4,
"win_odds": "1/5",
"win_decimal": 1.2,
"win_pool": 13929.0
}
]
}
]
}
],
"note": "TVG's public race board, read every 30 seconds while a race is open and once more when it is official. Odds are odds-to-1 as TVG sends them, with a decimal price beside each (1 + odds). win_odds is null until the WIN pool opens and on a scratched runner. Pool amounts are USD as TVG reports them. Times are UTC; date is the US Eastern race date."
}
GET /v1/racing/acceptances — Full-day AU thoroughbred acceptance card: every meeting, race and runnerGET /v1/racing/best-odds — Best racing price per runner across booksGET /v1/racing/changes — Races and prices that changed since a timestampPOST /v1/racing/clv — Score bets against the closing line (CLV)GET /v1/racing/consensus — The market consensus on one race: margin-free probability per runnerGET /v1/racing/events — Upcoming race listGET /v1/racing/form — Every runner in one race with its recent runs, from our own resultsGET /v1/racing/greyhounds/field — Every dog in one greyhound race with its recent runs, from our own resultsThe free tier needs no credit card, and the sandbox endpoints need no key at all.
Get a free API key Quickstart