This guide walks through fetching current odds for a sport, understanding the response structure, and filtering by sportsbook and market type.
Fetching Events with Odds
The primary endpoint for odds data is:
GET /api/v2/sports/{sportID}/events/{date}
Use the market_ids parameter to specify which market types to include. The three core markets are:
| Market | ID | Description |
|---|
| Moneyline | 1 | Who wins the game |
| Point Spread | 2 | Handicap / spread |
| Total (Over/Under) | 3 | Combined score |
curl "https://therundown.io/api/v2/sports/4/events/2026-02-12?key=YOUR_API_KEY&market_ids=1,2,3"
Understanding the Response Structure
The V2 response follows a nested hierarchy:
event
└── markets[] # Array of market types (moneyline, spread, total, etc.)
├── market_id # Numeric market identifier
├── name # Human-readable market name
└── participants[] # Teams or players in this market
├── participant_id # Unique participant identifier
├── name # Participant name (team or player)
└── lines[] # Available lines for this participant
├── line # Line value (e.g., -3.5 for spread)
├── is_main # Whether this is the primary line
└── prices{} # Map of affiliate_id → price object
├── price # American odds (e.g., -110, +150)
├── affiliate_id
└── timestamp
Here is a condensed example response for a single event:
{
"events": [
{
"event_id": "abc123",
"sport_id": 4,
"teams": [
{ "team_id": 1, "name": "Boston Celtics" },
{ "team_id": 2, "name": "Los Angeles Lakers" }
],
"markets": [
{
"market_id": 1,
"name": "Moneyline",
"period_id": 0,
"participants": [
{
"participant_id": 1,
"name": "Boston Celtics",
"lines": [
{
"line": null,
"is_main": true,
"prices": {
"19": { "price": -150, "affiliate_id": 19 },
"23": { "price": -145, "affiliate_id": 23 }
}
}
]
},
{
"participant_id": 2,
"name": "Los Angeles Lakers",
"lines": [
{
"line": null,
"is_main": true,
"prices": {
"19": { "price": 130, "affiliate_id": 19 },
"23": { "price": 125, "affiliate_id": 23 }
}
}
]
}
]
},
{
"market_id": 2,
"name": "Point Spread",
"period_id": 0,
"participants": [
{
"participant_id": 1,
"name": "Boston Celtics",
"lines": [
{
"line": -3.5,
"is_main": true,
"prices": {
"19": { "price": -110, "affiliate_id": 19 }
}
}
]
}
]
}
]
}
]
}
Filtering by Sportsbook
Use the affiliate_ids parameter to limit results to specific sportsbooks. This reduces payload size and focuses on the books you care about.
# Only DraftKings (19) and FanDuel (23)
curl "https://therundown.io/api/v2/sports/4/events/2026-02-12?\
key=YOUR_API_KEY&market_ids=1,2,3&affiliate_ids=19,23"
Common affiliate IDs:
| Sportsbook | ID |
|---|
| DraftKings | 19 |
| FanDuel | 23 |
| BetMGM | 22 |
| ESPN Bet | 24 |
| Pinnacle | 3 |
See Sportsbook IDs for the full list.
Main Lines vs. Alternates
By default, the API returns both main lines and alternate lines. Alternate lines are additional spread/total values offered by sportsbooks (e.g., -2.5, -3.0, -3.5, -4.0 for a spread market).
To fetch only the primary line for each market, add main_line=true:
curl "https://therundown.io/api/v2/sports/4/events/2026-02-12?\
key=YOUR_API_KEY&market_ids=1,2,3&main_line=true"
When main_line=true is set, each participant will have at most one line object per market, and its is_main field will be true. This is recommended for odds screens where you only need the consensus line.
Handling the 0.0001 Sentinel Value
A price value of 0.0001 means the line is off the board — the sportsbook has temporarily removed it. This commonly happens when:
- A key injury is being evaluated
- The book is recalculating after sharp action
- The market is approaching game time suspension
Never display 0.0001 to end users or use it in calculations. Show “Off Board” or “N/A” instead.
def format_price(price_value):
"""Format a price for display, handling sentinel values."""
if price_value == 0.0001:
return "Off Board"
if price_value > 0:
return f"+{int(price_value)}"
return str(int(price_value))
# Usage
for event in data["events"]:
for market in event.get("markets", []):
for participant in market["participants"]:
for line in participant["lines"]:
for aff_id, price_obj in line["prices"].items():
display = format_price(price_obj["price"])
print(f"{participant['name']}: {display}")
Full Working Example
Here is a complete example that fetches NBA odds, filters to DraftKings and FanDuel, and prints a formatted table:
import requests
from datetime import date
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://therundown.io/api/v2"
BOOKS = {"19": "DraftKings", "23": "FanDuel"}
response = requests.get(
f"{BASE_URL}/sports/4/events/{date.today()}",
params={
"key": API_KEY,
"market_ids": "1,2,3",
"affiliate_ids": "19,23",
"main_line": "true",
}
)
data = response.json()
def fmt(price):
if price == 0.0001:
return "N/A"
return f"+{int(price)}" if price > 0 else str(int(price))
for event in data["events"]:
away = event["teams"][0]["name"]
home = event["teams"][1]["name"]
print(f"\n{'=' * 60}")
print(f"{away} @ {home}")
print(f"{'=' * 60}")
for market in event.get("markets", []):
print(f"\n {market['name']}:")
for participant in market["participants"]:
for line in participant["lines"]:
line_str = f" ({line['line']})" if line.get("line") else ""
prices_str = " ".join(
f"{BOOKS.get(aid, aid)}: {fmt(p['price'])}"
for aid, p in line["prices"].items()
)
print(f" {participant['name']}{line_str}: {prices_str}")
Next Steps