Skip to main content

Unofficial Python SDK for The Odds API

Project description

The Odds API Python SDK

PyPI version Python Version PyPI Downloads License: MIT

An unofficial Python SDK for The Odds API.

Features

  • Type Safe: Full type hints and dataclass models
  • Efficient: Minimal dependencies, smart error handling
  • Well Documented: Extensive examples and docstrings

Quick Start

Installation

pip install the-odds-api-sdk

Basic Usage

from the_odds_api_sdk import OddsAPIClient

# Initialize client
client = OddsAPIClient(api_key="your-api-key")

# Get all sports
sports = client.get_sports()
print(f"Found {len(sports)} sports")

# Get NFL odds with enhanced features
nfl_odds = client.get_odds(
    "americanfootball_nfl", 
    regions=["us"],
    include_links=True,      # Include bookmaker links
    include_sids=True,       # Include source IDs
    include_bet_limits=True  # Include bet limits
)

for event in nfl_odds:
    print(f"{event.away_team} @ {event.home_team}")

API Coverage

Core Endpoints

get_sports(all_sports=False)List[Sport]

Get available sports with option to include inactive sports.

# Get only in-season sports
sports = client.get_sports()

# Get all sports including inactive ones
all_sports = client.get_sports(all_sports=True)

get_events(sport, **options)List[EventWithoutOdds]

Get events without odds (free endpoint, doesn't count against quota).

# Get all upcoming events for free
events = client.get_events("americanfootball_nfl")

# Filter by time range
from datetime import datetime, timedelta
tomorrow = datetime.now() + timedelta(days=1)
events = client.get_events(
    "americanfootball_nfl",
    commence_time_from=tomorrow
)

get_participants(sport)List[Participant]

Get participants (teams or players) for a sport.

# Get NFL teams
teams = client.get_participants("americanfootball_nfl")
for team in teams:
    print(f"{team.full_name} (ID: {team.id})")

# Get tennis players
players = client.get_participants("tennis")

get_odds(sport, **options)List[Event]

Get odds with comprehensive filtering and enhanced features.

# Enhanced odds with all features
odds = client.get_odds(
    sport="americanfootball_nfl",
    regions=["us", "uk"],
    markets=["h2h", "spreads", "totals"],
    odds_format="american",
    include_links=True,        # Bookmaker links to events/markets
    include_sids=True,         # Source IDs from bookmakers  
    include_bet_limits=True,   # Bet limits (mainly for exchanges)
    commence_time_from=datetime.now(),
    event_ids=["event1", "event2"]  # Filter specific events
)

get_event_odds(sport, event_id, **options)Event

Get comprehensive odds for a specific event including player props.

# Get all available markets for an event
event = client.get_event_odds(
    sport="americanfootball_nfl",
    event_id="event-id-123",
    regions=["us"],
    markets=["h2h", "spreads", "totals", "player_pass_tds", "player_rushing_yards"],
    include_links=True,
    include_sids=True,
    include_bet_limits=True
)

get_scores(sport, **options)List[EventScore]

Get live and completed game scores.

# Live and upcoming games only (quota cost: 1)
live_scores = client.get_scores("americanfootball_nfl")

# Include completed games from last 3 days (quota cost: 2)
all_scores = client.get_scores("americanfootball_nfl", days_from=3)

# Find completed games with scores
completed = [s for s in all_scores if s.completed and s.scores]
for game in completed:
    print(f"{game.away_team} @ {game.home_team}")
    for score in game.scores:
        print(f"  {score.name}: {score.score}")

Historical Data Endpoints

get_historical_odds(sport, date, **options)HistoricalSnapshot

Get historical odds data at a specific point in time.

from datetime import datetime

# Get odds as they appeared on a specific date
snapshot = client.get_historical_odds(
    sport="americanfootball_nfl",
    date="2023-10-10T12:15:00Z",  # or datetime object
    regions=["us"],
    markets=["h2h", "spreads"]
)

print(f"Snapshot from: {snapshot.timestamp}")
print(f"Previous: {snapshot.previous_timestamp}")
print(f"Next: {snapshot.next_timestamp}")
print(f"Events: {len(snapshot.data)}")

get_historical_events(sport, date, **options)HistoricalSnapshot

Get historical events data at a specific point in time.

# Get events as they appeared historically
events_snapshot = client.get_historical_events(
    sport="americanfootball_nfl",
    date=datetime(2023, 10, 10, 12, 0, 0),
    commence_time_from="2023-10-10T00:00:00Z"
)

get_historical_event_odds(sport, event_id, date, **options)HistoricalSnapshot

Get historical odds for a specific event including player props.

# Get historical player prop odds
event_snapshot = client.get_historical_event_odds(
    sport="americanfootball_nfl",
    event_id="event-id-123",
    date="2023-10-10T12:15:00Z",
    regions=["us"],
    markets=["player_pass_tds", "alternate_spreads"]
)

Data Models

All models now include optional enhanced fields:

@dataclass(frozen=True)
class Sport:
    key: str
    group: str
    title: str
    description: str
    active: bool
    has_outrights: bool

@dataclass(frozen=True)
class Participant:
    id: str
    full_name: str

@dataclass(frozen=True)
class Outcome:
    name: str
    price: Union[float, int]
    point: Optional[float] = None          # For spreads/totals
    description: Optional[str] = None      # Additional outcome info
    link: Optional[str] = None             # Bookmaker betslip link
    sid: Optional[str] = None              # Bookmaker source ID
    bet_limit: Optional[float] = None      # Bet limit (exchanges)

@dataclass(frozen=True)
class Market:
    key: str
    outcomes: List[Outcome]
    last_update: Optional[datetime] = None
    link: Optional[str] = None             # Market link
    sid: Optional[str] = None              # Market source ID

@dataclass(frozen=True)
class Bookmaker:
    key: str
    title: str
    last_update: Optional[datetime]
    markets: List[Market]
    link: Optional[str] = None             # Event link
    sid: Optional[str] = None              # Event source ID

@dataclass(frozen=True)
class Score:
    name: str
    score: Optional[Union[str, int]] = None

@dataclass(frozen=True)
class Event:
    id: str
    sport_key: str
    sport_title: str                       # Display name of sport
    commence_time: datetime
    home_team: Optional[str]
    away_team: Optional[str]
    bookmakers: List[Bookmaker]

@dataclass(frozen=True)
class EventScore:
    id: str
    sport_key: str
    sport_title: str
    commence_time: datetime
    completed: bool
    home_team: Optional[str]
    away_team: Optional[str]
    scores: Optional[List[Score]] = None
    last_update: Optional[datetime] = None

@dataclass(frozen=True)
class EventWithoutOdds:
    id: str
    sport_key: str
    sport_title: str
    commence_time: datetime
    home_team: Optional[str]
    away_team: Optional[str]

@dataclass(frozen=True)
class HistoricalSnapshot:
    timestamp: datetime                    # Snapshot timestamp
    previous_timestamp: Optional[datetime] # Previous available snapshot
    next_timestamp: Optional[datetime]     # Next available snapshot
    data: Union[List[Event], List[EventWithoutOdds], Event]

Advanced Examples

Complete Odds Analysis with Enhanced Features

def analyze_odds_with_links(sport_key: str):
    """Comprehensive odds analysis with bookmaker links."""
    
    # Get odds with all enhanced features
    odds = client.get_odds(
        sport_key,
        regions=["us"],
        markets=["h2h", "spreads", "totals"],
        include_links=True,
        include_sids=True,
        include_bet_limits=True
    )
    
    for event in odds:
        print(f"\n{event.away_team} @ {event.home_team}")
        print(f"Event ID: {event.id}")
        
        for bookmaker in event.bookmakers:
            print(f"\n  {bookmaker.title}")
            if bookmaker.link:
                print(f"    Event Link: {bookmaker.link}")
            
            for market in bookmaker.markets:
                print(f"    Market: {market.key}")
                if market.link:
                    print(f"      Market Link: {market.link}")
                
                for outcome in market.outcomes:
                    print(f"      {outcome.name}: {outcome.price}")
                    if outcome.link:
                        print(f"        Bet Link: {outcome.link}")
                    if outcome.bet_limit:
                        print(f"        Limit: ${outcome.bet_limit}")

# Usage
analyze_odds_with_links("americanfootball_nfl")

Historical Odds Tracking

def track_odds_movement(sport: str, event_id: str, hours_back: int = 24):
    """Track odds movement over time."""
    from datetime import datetime, timedelta
    
    snapshots = []
    current_time = datetime.now()
    
    # Get snapshots every hour for the past day
    for i in range(hours_back):
        snapshot_time = current_time - timedelta(hours=i)
        try:
            snapshot = client.get_historical_event_odds(
                sport=sport,
                event_id=event_id,
                date=snapshot_time,
                regions=["us"],
                markets=["h2h"]
            )
            snapshots.append(snapshot)
        except Exception:
            continue  # Snapshot might not exist
    
    # Analyze movement
    for snapshot in reversed(snapshots):
        print(f"\nTimestamp: {snapshot.timestamp}")
        if isinstance(snapshot.data, Event):
            event = snapshot.data
            for bookmaker in event.bookmakers:
                for market in bookmaker.markets:
                    if market.key == "h2h":
                        for outcome in market.outcomes:
                            print(f"  {outcome.name}: {outcome.price}")

# Usage
track_odds_movement("americanfootball_nfl", "event-id-123")

Free Event Discovery

def discover_upcoming_events():
    """Use the free events endpoint to discover upcoming games."""
    
    # Get sports first
    sports = client.get_sports()
    
    for sport in sports[:5]:  # Check first 5 sports
        try:
            events = client.get_events(sport.key)
            if events:
                print(f"\n{sport.title} ({len(events)} events):")
                for event in events[:3]:  # Show first 3 events
                    print(f"  {event.away_team} @ {event.home_team}")
                    print(f"    {event.commence_time}")
                    print(f"    ID: {event.id}")
        except Exception as e:
            print(f"Error getting {sport.title}: {e}")

# Usage (free - doesn't count against quota)
discover_upcoming_events()

Authentication

# Method 1: Direct initialization
client = OddsAPIClient(api_key="your-api-key")

# Method 2: Environment variable (recommended)
# Set ODDS_API_KEY=your-api-key
client = OddsAPIClient()

# Method 3: Context manager for automatic cleanup
with OddsAPIClient(api_key="your-api-key") as client:
    sports = client.get_sports()

All Available Parameters

Parameter Type Endpoints Description
all_sports bool get_sports Include inactive sports
regions List[Region] odds endpoints ["us", "us2", "uk", "au", "eu", "us_dfs"]
markets List[str] odds endpoints ["h2h", "spreads", "totals", "outrights", ...]
odds_format OddsFormat odds endpoints "decimal" or "american"
date_format DateFormat all endpoints "iso" or "unix"
include_links bool odds endpoints Include bookmaker links
include_sids bool odds endpoints Include source IDs
include_bet_limits bool odds endpoints Include bet limits
bookmakers List[str] odds endpoints Filter by bookmaker keys
event_ids List[str] multiple Filter by event IDs
commence_time_from datetime|str multiple Start time filter
commence_time_to datetime|str multiple End time filter
days_from int get_scores Include completed games
date datetime|str historical Historical snapshot date

Error Handling

from the_odds_api_sdk import (
    OddsAPIError,
    OddsAPIAuthError,
    OddsAPINotFoundError,
    OddsAPIRateLimitError,
    OddsAPIServerError
)

try:
    odds = client.get_odds("americanfootball_nfl", regions=["us"])
except OddsAPIAuthError:
    print("Invalid API key")
except OddsAPIRateLimitError:
    print("Rate limit exceeded")
except OddsAPINotFoundError:
    print("Sport or event not found")
except OddsAPIServerError:
    print("API server error")
except OddsAPIError as e:
    print(f"General API error: {e}")

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Links

Tips

  1. Use Environment Variables: Store your API key in ODDS_API_KEY environment variable
  2. Cache Results: The API has rate limits, so cache responses when possible
  3. Filter Wisely: Use specific regions and markets to reduce API usage
  4. Handle Timezones: All times are in UTC by default
  5. Monitor Usage: Check your API usage at the-odds-api.com

Disclaimer

This is an unofficial SDK and is not affiliated with, endorsed by, or connected to The Odds API or its official developers.

This SDK is provided "as is" without warranty of any kind. Use at your own risk.

For official support, please contact The Odds API directly.


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

the_odds_api_sdk-1.0.1.tar.gz (24.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

the_odds_api_sdk-1.0.1-py3-none-any.whl (14.8 kB view details)

Uploaded Python 3

File details

Details for the file the_odds_api_sdk-1.0.1.tar.gz.

File metadata

  • Download URL: the_odds_api_sdk-1.0.1.tar.gz
  • Upload date:
  • Size: 24.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.0

File hashes

Hashes for the_odds_api_sdk-1.0.1.tar.gz
Algorithm Hash digest
SHA256 cb294946c86527d82716d703b8ed4d4a8e9e897fc8ce31bf3a5edb750c5b016c
MD5 76bbca372329530b1f8c28341509c1f0
BLAKE2b-256 469d3fb9d26e21f3b0d58bfa43db090051955eca205db0fd617c9f0ddaa88155

See more details on using hashes here.

File details

Details for the file the_odds_api_sdk-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for the_odds_api_sdk-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 885391b7a109fec85184a66c8cfb252876e9368328d95d8f8d2ee69a641260bd
MD5 bb5940d0c28b20a5ee97d2eb9b0a18c6
BLAKE2b-256 5934fb29828c71f09d1821e5321d938f956c9922ec4f5f39d7cd32780156878f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page