Odds337Docs
    Odds337BackGet API key
    Getting started
    • Introduction
    • Authentication
    • Quickstart
    • Tokens & pricing
    • Limits
    • Errors
    • Odds formats
    Reference
    • GET/sports
    • GET/books
    • GET/teams
    • GET/players
    • Logos & headshots
    • GET/events
    • GET/odds
    • GET/scores
    • GET/history
    • GET/clv
    • POST /clv
    • GET/usage
    • GET/_health
    • WebSocket
    • Specs & SDKs
    Racing
    • GET/racing/meetings
    • GET/racing/race
    • GET/racing/history
    • race_id and status
    Concepts
    • event_id
    • selection_key
    • team_id & player_id
    • Open & close prices
    • 337 model price
    • Event links
    • Statuses
    Getting started
    • Introduction
    • Authentication
    • Quickstart
    • Tokens & pricing
    • Limits
    • Errors
    • Odds formats
    Reference
    • GET/sports
    • GET/books
    • GET/teams
    • GET/players
    • Logos & headshots
    • GET/events
    • GET/odds
    • GET/scores
    • GET/history
    • GET/clv
    • POST /clv
    • GET/usage
    • GET/_health
    • WebSocket
    • Specs & SDKs
    Racing
    • GET/racing/meetings
    • GET/racing/race
    • GET/racing/history
    • race_id and status
    Concepts
    • event_id
    • selection_key
    • team_id & player_id
    • Open & close prices
    • 337 model price
    • Event links
    • Statuses

    Racing

    Get a race

    One race: every book's fixed win and place price, Betfair back and lay, and the result.

    GET/odds/v1/racing/race
    Cost
    1 token
    Authentication
    X-API-Key, demo key works

    Parameters

    • race_idstringrequired
      A race_id from /racing/meetings.
    • bookscomma listoptional
      Only these books, e.g. sportsbet,tab,ladbrokes.Default: all books
    • formatstringoptional
      decimal, american or fractional. See Odds formats.Default: decimal

    Request

    # Take the first race of the first AU thoroughbred meeting, then price it
    RACE_ID=$(curl -s "https://api.b337.ai/odds/v1/racing/meetings?country=au&race_type=thoroughbred" \
      -H "X-API-Key: demo" | jq -r '.data[0].races[0].race_id')
    
    curl -sG "https://api.b337.ai/odds/v1/racing/race" \
      --data-urlencode "race_id=$RACE_ID" \
      --data-urlencode "books=sportsbet,tab,ladbrokes" \
      -H "X-API-Key: demo" --compressed
    import requests
    
    BASE = "https://api.b337.ai/odds/v1"
    HEADERS = {"X-API-Key": "demo"}
    
    meetings = requests.get(f"{BASE}/racing/meetings", headers=HEADERS, timeout=10,
                            params={"country": "au", "race_type": "thoroughbred"}).json()
    race_id = meetings["data"][0]["races"][0]["race_id"]
    
    race = requests.get(f"{BASE}/racing/race", headers=HEADERS, timeout=10, params={
        "race_id": race_id,
        "books": "sportsbet,tab,ladbrokes",
    }).json()
    
    for runner in race["runners"]:
        if runner["scratched"]:
            continue
        best = max(runner["books"].items(), key=lambda kv: kv[1]["win"])
        print(runner["number"], runner["name"], "best win:", best[0], best[1]["win"])
    // Node 18+, saved as an .mjs file
    const BASE = "https://api.b337.ai/odds/v1";
    const headers = { "X-API-Key": "demo" };
    
    const meetings = await (await fetch(`${BASE}/racing/meetings?country=au&race_type=thoroughbred`, { headers })).json();
    const raceId = meetings.data[0].races[0].race_id;
    
    const url = new URL(`${BASE}/racing/race`);
    url.searchParams.set("race_id", raceId);
    url.searchParams.set("books", "sportsbet,tab,ladbrokes");
    
    const race = await (await fetch(url, { headers })).json();
    for (const r of race.runners) console.log(r.number, r.name, r.books);

    Response

    200 OK
    {"schema_version": 1, "race_id": "gawler/4/(R)/au/2026-10-05",
     "meeting_id": "gawler/(R)/au/2026-10-05", "venue": "Gawler", "country": "au",
     "race_type": "thoroughbred", "race_type_code": "R", "race_number": 4, "date": "2026-10-05",
     "start_time": "2026-10-05T05:10:00Z", "betfair_status": "OPEN", "in_play": false,
     "race_state": "upcoming", "abandoned": false, "distance_m": 1100, "race_class": "CL1",
     "betfair_market_ids": {"win": "1.263274446", "place_3": "1.263274447"},
     "books": ["123bet", "allbets", "baggybet", "ballrbet", "bet365", "bet66", "..."],
     "book_urls": {"betdeluxe": "https://www.betdeluxe.com.au/racing/Thoroughbred/AUS/gawler/829483/4/11830376"},
     "runners": [
      {"number": 1, "name": "Super Choice", "scratched": false, "selection_id": 103415948,
       "books": {"123bet": {"win": 3.2, "place": 1.28, "changed_at": "2026-10-05T03:39:11Z"},
                 "allbets": {"win": 3.5, "place": 1.5, "changed_at": "2026-10-05T03:44:06Z"},
                 "baggybet": {"win": 3.4, "place": 1.38}},
       "betfair": {"win": {"back": 4.1, "lay": 5.7, "back_size": 1.9, "lay_size": 5.01},
                   "place_3": {"back": 1.55, "lay": 3.05, "back_size": 13.49, "lay_size": 71.41}},
       "tote": {"nsw": {"win": 3.6, "place": 1.4}, "vic": {"win": 3.5, "place": 1.4}},
       "finish_position": null},
      {"number": 2, "name": "Leliyn", "...": "..."}],
     "source": "terminal_snapshot", "as_of": "2026-10-05T04:13:18Z",
     "betfair_matched": {"win": 372.61, "place_3": 0.0},
     "tote_pools": {"nsw": {"win": {"pool_total": 5120.4, "status": "Open", "jackpot": 0.0},
                            "place": {"pool_total": 1633.9, "status": "Open", "jackpot": 0.0}}},
     "tote_updated_at": "2026-10-05T04:13:40Z", "result": null,
     "odds_format": "decimal", "generated_at": "2026-10-05T04:14:03Z"}
    
    // The same race once it has finished (trimmed):
    {"race_id": "gawler/1/(R)/au/2026-10-05", "betfair_status": "CLOSED", "in_play": false,
     "race_state": "finalised", "source": "spine",
     "runners": [
      {"number": 9, "name": "Miami Miller", "scratched": false,
       "books": {"tab": {"win": 81.0, "place": 10.0, "changed_at": "2026-10-05T03:25:36Z"}},
       "betfair": {}, "finish_position": "1st"},
      {"number": 1, "name": "Ateyate", "scratched": false, "selection_id": 98273722,
       "books": {"ladbrokes": {"win": 11.0, "place": 2.35, "changed_at": "2026-10-05T03:26:16Z"}},
       "betfair": {}, "finish_position": null, "bsp": {"win": 16.0, "place": 3.0},
       "tote": {"nsw": {"win": 12.6, "place": 2.4}, "vic": {"win": 12.1, "place": 2.3}}}],
     "tote_pools": {"nsw": {"win": {"pool_total": 31058.62, "status": "Closed", "jackpot": 0.0},
                            "place": {"pool_total": 8202.98, "status": "Closed", "jackpot": 0.0}}},
     "tote_updated_at": "2026-10-05T03:26:19Z",
     "result": {"source": "tab", "official": true, "tab_status": "Paying",
                "placings": [[9], [4], [6], [7]],
                "dividends": {"nsw": {"win": [{"runners": [9], "dividend": 70.3}],
                                      "place": [{"runners": [9], "dividend": 9.3},
                                                {"runners": [4], "dividend": 1.2},
                                                {"runners": [6], "dividend": 1.8}],
                                      "quinella": [{"runners": [9, 4], "dividend": 83.6}]}},
                "scratchings": [], "updated_at": "2026-10-05T03:37:15Z"}}

    Fields

    • runners[] carry number (saddlecloth or box), name, scratched and, where we hold it, the Betfair selection_id. finish_position is set once the race has a result.
    • books[book].win and place are the book's fixed odds. changed_at is when that book's price last changed; see changed_at. A book that does not price a runner is absent.
    • betfair holds win and, where Betfair runs them, place_2 and place_3, each with back, lay, back_size and lay_size. bsp (win and place) appears once the race is off.
    • tote.nsw and tote.vic are TAB's win and place approximates (dollars per $1) for AU and NZ races, from about 30 minutes out. tote_pools holds each pool's pool_total ($), status and jackpot, per jurisdiction; tote_updated_at is when TAB last updated them. Tote values are dollars and are never converted by format.
    • book_urls maps a book to its own page for the race, where we hold its id. betfair_matched is the money matched per Betfair market.
    • source says where the body came from: terminal_snapshot (a race with live prices; the as_of time is when it was built), spine (the field from our race record and, for a finished race, each book's last recorded price) or results_store (only the result is left).
    • result is null until TAB has one. placings is a list of saddlecloth numbers per finishing slot; a dead heat puts several numbers in one slot and leaves the next slot empty. official is true once TAB is paying. dividends (and multi_dividends for the multi-race pools) are per $1 staked, stake included, per jurisdiction and pool, as runners plus dividend. scratchings lists the scratched runners.
    • A finished race's books prices are each book's last recorded price, which can be a tick taken just after the scheduled start. Check changed_at.
    • format converts every book and Betfair price; see odds formats.

    Tote fields are AU and NZ TAB only and appear once TAB has published them: tote, tote_pools, tote_updated_at and result.dividends. Placings and scratchings are always served.

    PreviousGET /racing/meetingsNextGET /racing/history

    On this page

    • Parameters
    • Request
    • Response
    • Fields