Getting started

Quickstart

Go from a new account to bet365 prices in four calls. You need a token and a terminal, Python or Node.js.

  1. Step 1

    Get a token

    Sign in, open the dashboard and copy your API token. Keep it in an environment variable rather than in your code.

    export ODDS_DATA_API_TOKEN="YOUR-TOKEN"
  2. Step 2

    List in-play events

    Ask for every soccer event in play right now with sport_id=1. Each event has our id, the bet365 fixture id in bet365_id, the score in ss and the clock in timer.

    curl "https://api.odds-data-api.com/v3/events/inplay?sport_id=1&token=$ODDS_DATA_API_TOKEN"
    application/json
    {
      "success": 1,
      "pager": {
        "page": 1,
        "per_page": 1000,
        "total": 2
      },
      "results": [
        {
          "id": "8204771",
          "sport_id": "1",
          "time": "1789237200",
          "time_status": "1",
          "league": {
            "id": "10041282",
            "name": "England Premier League",
            "cc": "gb"
          },
          "home": {
            "id": "10204",
            "name": "Brentford",
            "image_id": null,
            "cc": "gb"
          },
          "away": {
            "id": "10218",
            "name": "Everton",
            "image_id": null,
            "cc": "gb"
          },
          "ss": "2-1",
          "scores": {
            "1": {
              "home": "1",
              "away": "0"
            },
            "2": {
              "home": "2",
              "away": "1"
            }
          },
          "timer": {
            "tm": 67,
            "ts": 12,
            "tt": "1",
            "ta": 0,
            "md": 1
          },
          "bet365_id": "158204771"
        },
        {
          "id": "8212001",
          "sport_id": "1",
          "time": "1789241100",
          "time_status": "1",
          "league": {
            "id": "10090001",
            "name": "Esoccer Battle - 8 mins play",
            "cc": null
          },
          "home": {
            "id": "90001",
            "name": "Liverpool (Marlin) Esports",
            "image_id": null,
            "cc": null
          },
          "away": {
            "id": "90002",
            "name": "Real Madrid (Cobalt) Esports",
            "image_id": null,
            "cc": null
          },
          "ss": "2-3",
          "timer": {
            "tm": 5,
            "ts": 41,
            "tt": "1",
            "ta": 0,
            "md": 1
          },
          "bet365_id": "158212001"
        }
      ]
    }

    The second result is an Esoccer event: it is listed under Soccer too. Leave it out with skip_esports=1 on the endpoints that take it. See Esports.

  3. Step 3

    View one event

    Pass the id from step 2 as event_id to get stats, timeline, stadium, referee and managers.

    curl "https://api.odds-data-api.com/v1/event/view?event_id=8204771&token=$ODDS_DATA_API_TOKEN"
    application/json
    {
      "success": 1,
      "results": [
        {
          "id": "8204771",
          "sport_id": "1",
          "time": "1789237200",
          "time_status": "1",
          "league": {
            "id": "10041282",
            "name": "England Premier League",
            "cc": "gb"
          },
          "home": {
            "id": "10204",
            "name": "Brentford",
            "image_id": null,
            "cc": "gb"
          },
          "away": {
            "id": "10218",
            "name": "Everton",
            "image_id": null,
            "cc": "gb"
          },
          "ss": "2-1",
          "scores": {
            "1": {
              "home": "1",
              "away": "0"
            },
            "2": {
              "home": "2",
              "away": "1"
            }
          },
          "timer": {
            "tm": 67,
            "ts": 12,
            "tt": "1",
            "ta": 0,
            "md": 1
          },
          "bet365_id": "158204771",
          "stats": {
            "attacks": [
              "88",
              "61"
            ],
            "dangerous_attacks": [
              "44",
              "29"
            ],
            "possession_rt": [
              "57",
              "43"
            ],
            "on_target": [
              "6",
              "3"
            ],
            "off_target": [
              "7",
              "5"
            ],
            "corners": [
              "6",
              "3"
            ],
            "yellowcards": [
              "2",
              "1"
            ]
          },
          "extra": {
            "home_manager": {
              "id": "53463",
              "name": "Tomás Duarte",
              "cc": "pt"
            },
            "away_manager": {
              "id": "1152",
              "name": "Hugo Keller",
              "cc": "de"
            },
            "referee": {
              "id": "107059",
              "name": "Chris Kavanagh",
              "cc": "gb"
            },
            "stadium_data": {
              "id": "606",
              "name": "Gtech Community Stadium",
              "city": "London",
              "country": "England"
            },
            "round": "4"
          },
          "events": [
            {
              "id": "69731159",
              "text": "15' - 1st Goal - (Brentford) -"
            },
            {
              "id": "69731190",
              "text": "58' - 3rd Goal - (Everton) -"
            }
          ],
          "has_lineup": 1,
          "inplay_created_at": "1789236300",
          "inplay_updated_at": "1789241232"
        }
      ]
    }
  4. Step 4

    Read bet365 odds

    Pass bet365_id from step 2 as FI to the Bet365 API. PreMatch Odds groups every market in sections: main, asian_lines, goals, half and others.

    curl "https://api.odds-data-api.com/v4/bet365/prematch?FI=158204771&token=$ODDS_DATA_API_TOKEN"
    application/json
    {
      "success": 1,
      "results": [
        {
          "FI": "158204771",
          "event_id": "8204771",
          "main": {
            "updated_at": "1789236000",
            "key": "main",
            "sp": {
              "full_time_result": {
                "id": "40",
                "name": "Full Time Result",
                "odds": [
                  {
                    "id": "962056610",
                    "odds": "2.45",
                    "name": "1"
                  },
                  {
                    "id": "962056617",
                    "odds": "3.60",
                    "name": "Draw"
                  },
                  {
                    "id": "962056618",
                    "odds": "2.80",
                    "name": "2"
                  }
                ]
              }
            }
          },
          "asian_lines": {
            "updated_at": "1789236000",
            "key": "asian_lines",
            "sp": {}
          },
          "goals": {
            "updated_at": "1789236000",
            "key": "goals",
            "sp": {}
          },
          "half": {
            "updated_at": "1789236000",
            "key": "half",
            "sp": {}
          },
          "others": []
        }
      ]
    }

    Pre-match prices stop updating at kickoff. For a live event, read the current prices from Bet365 Inplay Event with the same FI. Market keys are listed in Market keys.

Poll within your limit

In-play prices change every few seconds. Poll on a fixed interval that fits your hourly limit, and stop polling an event once its time_status is final.

  • 3,600 requests per hour is one request per second across all the events you follow.
  • Read X-RateLimit-Remaining on every response and slow down before it reaches zero.
  • On TOO_MANY_REQUESTS, wait until X-RateLimit-Reset instead of retrying at once.
import os, time, requests

API = "https://api.odds-data-api.com"
TOKEN = os.environ["ODDS_DATA_API_TOKEN"]

def get(path, **params):
    while True:
        res = requests.get(API + path, params={**params, "token": TOKEN})
        data = res.json()
        if data["success"] == 1:
            return data
        if data["error"] == "TOO_MANY_REQUESTS":
            # Wait until the hourly window resets, then retry.
            reset = int(res.headers["X-RateLimit-Reset"])
            time.sleep(max(reset - time.time(), 1))
            continue
        raise RuntimeError(data["error"] + " " + data.get("error_detail", ""))

while True:
    event = get("/v1/bet365/event", FI="158204771")
    # Update your model with event["results"]
    time.sleep(2)

Limits per plan and the response headers are in Rate limits.