Guide
Quickstart
Get a key and make your first call in under a minute.
1. Get a key
Open /api/manage, start the 3-day trial (no card) and copy the key it shows you. Keys look like tbi_live_… and are shown once — if you lose one, revoke it and create another. Trials include 2,000 requests at 30 requests/minute.
2. Your first call
Every Chiefs game in the 2024 regular season, with final score, consensus closing line and whether the home side covered:
curl "https://api.thebettinginsider.com/v1/games?sport=nfl&season=2024&team=KC&season_type=regular&limit=2" \
-H "Authorization: Bearer tbi_live_YOUR_KEY"{
"data": [
{
"game_id": "NFL-20240905-BAL-KC",
"sport": "nfl",
"season": 2024,
"season_type": "regular",
"week": 1,
"game_date": "2024-09-05",
"start_time": "2024-09-06T00:40:00.000Z",
"status": "final",
"home": {
"team_id": 139,
"abbreviation": "KC",
"name": "Kansas City Chiefs",
"score": 27
},
"away": {
"team_id": 126,
"abbreviation": "BAL",
"name": "Baltimore Ravens",
"score": 20
},
"neutral_site": false,
"overtime": null,
"venue": {
"venue_id": 2300,
"name": "GEHA Field at Arrowhead Stadium",
"city": "Kansas City",
"indoor": false
},
"referee": "Shawn Hochuli",
"result": {
"margin_home": 7,
"home_covered": true,
"went_over": null,
"favorite": "home"
},
"consensus": {
"moneyline": {
"home_open": -148,
"home_close": -148,
"away_open": 124,
"away_close": 124
},
"spread": {
"open": -3,
"close": -3,
"home_juice_open": null,
"home_juice_close": -105,
"away_juice_open": null,
"away_juice_close": -115
},
"total": {
"open": 46.5,
"close": 47,
"over_juice_close": -112,
"under_juice_close": -108
}
}
},
{
"game_id": "NFL-20240915-CIN-KC",
"sport": "nfl",
"season": 2024,
"season_type": "regular",
"week": 2,
"game_date": "2024-09-15",
"start_time": "2024-09-15T20:25:00.000Z",
"status": "final",
"home": {
"team_id": 139,
"abbreviation": "KC",
"name": "Kansas City Chiefs",
"score": 26
},
"away": {
"team_id": 130,
"abbreviation": "CIN",
"name": "Cincinnati Bengals",
"score": 25
},
"neutral_site": false,
"overtime": null,
"venue": {
"venue_id": 2300,
"name": "GEHA Field at Arrowhead Stadium",
"city": "Kansas City",
"indoor": false
},
"referee": "Alex Kemp",
"result": {
"margin_home": 1,
"home_covered": false,
"went_over": true,
"favorite": "home"
},
"consensus": {
"moneyline": {
"home_open": -180,
"home_close": -285,
"away_open": 150,
"away_close": 235
},
"spread": {
"open": -3.5,
"close": -6.5,
"home_juice_open": null,
"home_juice_close": -115,
"away_juice_open": null,
"away_juice_close": -105
},
"total": {
"open": 48.5,
"close": 48,
"over_juice_close": -105,
"under_juice_close": -115
}
}
}
],
"next_cursor": "eyJrIjp7InQiOiIyMDI0LTA5LTE1IDIwOjI1OjAwLjAwMCIsImlkIjoiTkZMLTIwMjQwOTE1LUNJTi1LQyJ9LCJmIjoiYWY0OWI3ZGQzN2NkIn0",
"meta": {
"count": 2,
"request_id": "d3c69063-3e97-4040-afe2-e045eb201d8d"
}
}data is the page, next_cursor is how you get the next one, and meta.request_id is what to quote if you write to support.
3. Page through results
Pass next_cursor back as ?cursor= with the same filters until it comes back null. Default page size is 100; ask for up to limit=1000.
import requests
API = "https://api.thebettinginsider.com/v1"
H = {"Authorization": "Bearer tbi_live_YOUR_KEY"}
params = {"sport": "nba", "season": 2024, "limit": 1000}
games = []
while True:
page = requests.get(f"{API}/games", headers=H, params=params).json()
games += page["data"]
if not page["next_cursor"]:
break
params["cursor"] = page["next_cursor"]
print(len(games), "games") # 1,300-ish for a full NBA season incl. playoffs
home_covers = sum(1 for g in games if g["result"]["home_covered"])
print("home covered", home_covers)const API = "https://api.thebettinginsider.com/v1";
const headers = { Authorization: "Bearer tbi_live_YOUR_KEY" };
async function* pages(path: string, params: Record<string, string>) {
let cursor: string | null = null;
do {
const url = new URL(API + path);
for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v);
if (cursor) url.searchParams.set("cursor", cursor);
const res = await fetch(url, { headers });
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const body = await res.json();
yield body.data;
cursor = body.next_cursor;
} while (cursor);
}
for await (const batch of pages("/games", { sport: "nhl", season: "2025", limit: "1000" })) {
console.log(batch.length);
}4. Pull a CSV
Any list endpoint streams CSV with ?format=csv (or Accept: text/csv). Nested objects are flattened to dotted columns (home.score, consensus.spread.close). The next cursor arrives in the X-Next-Cursor header.
curl "https://api.thebettinginsider.com/v1/odds?sport=mlb&season=2025&market=total&book=draftkings&limit=1000&format=csv" \
-H "Authorization: Bearer tbi_live_YOUR_KEY" -D headers.txt -o mlb_2025_dk_totals.csv
grep -i x-next-cursor headers.txtWhere next
- GET /v1/games — the core table; GET /v1/games/:id adds every book, period lines, period scores and weather.
- GET /v1/odds — one row per game per book, graded against that book's own close.
- Data conventions — read this before you compute anything.