This guide provides everything developers need to integrate with the AltSportsLeagues.ai platform. Whether you're building for league owners, sportsbooks, or creating your own sports betting application, our APIs and SDKs make integration straightforward.
π― Development Options
Choose Your Integration Method
| Method | Best For | Complexity | Speed |
|---|---|---|---|
| Python SDK | Full-featured applications | Low | Fast |
| REST API | Web apps, mobile apps | Medium | Medium |
| Webhook Events | Real-time integrations | Medium | Fast |
| Data Feeds | Analytics, reporting | High | Variable |
π Quick Start with Python SDK
Installation
# Install the SDK
pip install altsportsleagues
# Or install with optional dependencies
pip install altsportsleagues[dev] # For development
pip install altsportsleagues[docs] # For documentation generationBasic Usage
from altsportsleagues import AltSportsLeagues
# Initialize client
client = AltSportsLeagues(api_key="your_api_key")
# Test connection
print(client.ping())
# Get available leagues
leagues = client.get_leagues()
print(f"Found {len(leagues)} leagues")
# Get events for a specific league
events = client.get_events(league_id="nba", limit=10)
print(f"NBA has {len(events)} upcoming events")π API Access & Authentication
Getting Your API Key
- Sign Up: Visit altsportsleagues.ai/signup (opens in a new tab)
- Choose Account Type: Select "Developer" or appropriate account type
- Verification: Complete email verification and basic profile setup
- API Access: Navigate to API settings to generate your key
Authentication Methods
API Key Authentication (Recommended)
from altsportsleagues import AltSportsLeagues
# Direct initialization
client = AltSportsLeagues(api_key="your_api_key_here")
# Or from environment variable
import os
client = AltSportsLeagues(api_key=os.getenv("ALTSPORTSLEAGUES_API_KEY"))JWT Token Authentication (Enterprise)
# For enterprise applications requiring user-specific access
import requests
# Get JWT token
auth_response = requests.post("https://api.altsportsleagues.ai/auth/login", json={
"email": "your_email@company.com",
"password": "your_password"
})
token = auth_response.json()["access_token"]
# Use with SDK
client = AltSportsLeagues(api_key=token)Environment Configuration
# Set environment variables
export ALTSPORTSLEAGUES_API_KEY="your_key_here"
export ALTSPORTSLEAGUES_BASE_URL="https://api.altsportsleagues.ai" # Optional
export ALTSPORTSLEAGUES_TIMEOUT="30" # Optional, seconds# Python configuration
import os
config = {
"api_key": os.getenv("ALTSPORTSLEAGUES_API_KEY"),
"base_url": os.getenv("ALTSPORTSLEAGUES_BASE_URL", "https://api.altsportsleagues.ai"),
"timeout": int(os.getenv("ALTSPORTSLEAGUES_TIMEOUT", "30"))
}
client = AltSportsLeagues(**config)π Core API Concepts
Data Models
Our platform revolves around three core entities:
Leagues
Sports leagues with compliance information and betting readiness status.
from altsportsleagues import League
# League properties
league = client.get_league("nba")
print(f"Name: {league.league_name}")
print(f"Sport: {league.sport_bucket}")
print(f"Compliance Score: {league.compliance_score}/100")
print(f"Status: {league.get_onboarding_progress()}")
print(f"Location: {league.location}")
print(f"Teams: {league.number_of_teams}")Events
Individual sporting events with teams, timing, and results.
from altsportsleagues import Event
# Event properties
event = client.get_events(league_id="nba", limit=1)[0]
print(f"Matchup: {event.home_team} vs {event.away_team}")
print(f"Start Time: {event.start_time}")
print(f"Venue: {event.venue}")
print(f"Status: {event.status}")
print(f"Season: {event.season}")
# Check if event is upcoming
if event.is_upcoming():
print("Event is upcoming")
# Get winner if completed
winner = event.get_winner()
if winner:
print(f"Winner: {winner}")Odds
Betting odds from various sportsbooks for events.
from altsportsleagues import Odds
# Odds properties
odds = client.get_odds("event_id")[0]
print(f"Bookmaker: {odds.bookmaker}")
print(f"Market: {odds.market}")
print(f"Live: {odds.is_live}")
print(f"Last Updated: {odds.last_updated}")
# Get best odds for a selection
best_moneyline = odds.get_best_odds("Los Angeles Lakers")
print(f"Best Lakers odds: {best_moneyline}")Sport Classifications
We categorize sports into buckets for better organization:
# Get available sport buckets
buckets = client.get_sport_buckets()
print(f"Available buckets: {buckets}")
# Output: ['combat', 'large_field', 'team', 'racing', 'other']
# Get all sports
sports = client.get_sports()
for sport in sports[:10]: # First 10 sports
print(f"{sport.name} ({sport.bucket}) - Popularity: {sport.popularity_score}")π οΈ Development Workflows
Building a League Management Dashboard
import streamlit as st
from altsportsleagues import AltSportsLeagues
# Initialize client
client = AltSportsLeagues(api_key=st.secrets["api_key"])
st.title("League Management Dashboard")
# Get all leagues
leagues = client.get_leagues()
# Filter options
sport_filter = st.selectbox("Filter by Sport", ["All"] + client.get_sport_buckets())
min_compliance = st.slider("Minimum Compliance Score", 0, 100, 70)
# Apply filters
filtered_leagues = leagues
if sport_filter != "All":
filtered_leagues = [l for l in leagues if l.sport_bucket == sport_filter]
filtered_leagues = [l for l in filtered_leagues if l.compliance_score >= min_compliance]
# Display results
st.write(f"Showing {len(filtered_leagues)} leagues")
for league in filtered_leagues[:20]: # Show first 20
with st.expander(f"{league.league_name} - Score: {league.compliance_score}"):
col1, col2, col3 = st.columns(3)
with col1:
st.write(f"**Sport:** {league.sport_bucket}")
st.write(f"**Location:** {league.location or 'N/A'}")
with col2:
st.write(f"**Teams:** {league.number_of_teams or 'N/A'}")
st.write(f"**Founded:** {league.founded_year or 'N/A'}")
with col3:
status = league.get_onboarding_progress()
st.write(f"**Status:** {status}")
# Get detailed compliance info
try:
compliance = client.get_compliance_status(league.league_id)
st.write(f"**Level:** {compliance['compliance_level']}")
except:
st.write("**Level:** Unknown")Creating a Betting Odds Aggregator
def create_odds_aggregator(client, event_ids):
"""
Aggregate odds from multiple sportsbooks for given events
"""
aggregated_data = {}
for event_id in event_ids:
try:
# Get event details
event_response = client._request('GET', f'/v1/events/{event_id}')
event = event_response['data']
# Get all odds for this event
odds_list = client.get_odds(event_id)
# Aggregate by market type
markets = {}
for odds in odds_list:
market_name = odds.market
if market_name not in markets:
markets[market_name] = {
'bookmakers': [],
'selections': {}
}
markets[market_name]['bookmakers'].append(odds.bookmaker)
# Aggregate odds for each selection
for selection in odds.selections:
sel_name = selection['name']
sel_odds = selection['odds']
if sel_name not in markets[market_name]['selections']:
markets[market_name]['selections'][sel_name] = {
'odds': [],
'best_odds': 0,
'bookmakers': []
}
markets[market_name]['selections'][sel_name]['odds'].append(sel_odds)
markets[market_name]['selections'][sel_name]['bookmakers'].append(odds.bookmaker)
# Track best odds
if sel_odds > markets[market_name]['selections'][sel_name]['best_odds']:
markets[market_name]['selections'][sel_name]['best_odds'] = sel_odds
aggregated_data[event_id] = {
'event': event,
'markets': markets
}
except Exception as e:
print(f"Error processing event {event_id}: {e}")
return aggregated_data
# Usage
nba_events = client.get_events(league_id="nba", limit=5)
event_ids = [event.event_id for event in nba_events]
odds_data = create_odds_aggregator(client, event_ids)
# Display aggregated odds
for event_id, data in odds_data.items():
event = data['event']
print(f"\n{event['home_team']} vs {event['away_team']}")
for market_name, market_data in data['markets'].items():
print(f" {market_name.upper()} ({len(market_data['bookmakers'])} books):")
for selection_name, sel_data in market_data['selections'].items():
best_odds = sel_data['best_odds']
num_books = len(sel_data['bookmakers'])
avg_odds = sum(sel_data['odds']) / len(sel_data['odds'])
print(f" {selection_name}: {best_odds:.2f} (avg: {avg_odds:.2f}, {num_books} books)")Real-Time Event Monitoring
import asyncio
import time
from datetime import datetime, timedelta
async def monitor_live_events(client, league_ids, callback=None):
"""
Monitor live events and odds changes
"""
while True:
current_time = datetime.now()
for league_id in league_ids:
try:
# Get live/upcoming events
events = client.get_events(
league_id=league_id,
start_date=current_time.isoformat(),
end_date=(current_time + timedelta(hours=24)).isoformat(),
limit=50
)
for event in events:
# Check if event is live or starting soon
event_time = datetime.fromisoformat(event.start_time.replace('Z', '+00:00'))
time_until_start = event_time - current_time
if event.status == 'in_progress':
# Live event - get latest odds
odds = client.get_odds(event.event_id)
if callback:
await callback('live_event', event, odds)
else:
print(f"LIVE: {event.home_team} vs {event.away_team}")
print(f" Status: {event.status}")
print(f" Score: {event.home_score}-{event.away_score}")
print(f" Odds sources: {len(odds)}")
elif 0 <= time_until_start.total_seconds() <= 3600: # Next hour
# Upcoming event - monitor odds changes
odds = client.get_odds(event.event_id)
if callback:
await callback('upcoming_event', event, odds)
else:
print(f"UPCOMING: {event.home_team} vs {event.away_team}")
print(f" Starts in: {time_until_start.total_seconds() / 60:.0f} minutes")
print(f" Odds sources: {len(odds)}")
except Exception as e:
print(f"Error monitoring {league_id}: {e}")
await asyncio.sleep(60) # Check every minute
# Usage
async def handle_event_update(event_type, event, odds):
"""Handle real-time event updates"""
if event_type == 'live_event':
print(f"π΄ LIVE UPDATE: {event.home_team} {event.home_score} - {event.away_score} {event.away_team}")
elif event_type == 'upcoming_event':
print(f"π UPCOMING: {event.home_team} vs {event.away_team}")
# Monitor NBA and NFL
asyncio.run(monitor_live_events(client, ['nba', 'nfl'], handle_event_update))π§ Advanced Integration Patterns
Webhook Integration
Set up webhooks for real-time event updates:
from flask import Flask, request
import json
app = Flask(__name__)
# Store for webhook events
event_updates = []
@app.route('/webhook/altsportsleagues', methods=['POST'])
def handle_webhook():
"""Handle AltSportsLeagues webhook events"""
data = request.get_json()
if data['event_type'] == 'event_completed':
event_updates.append({
'event_id': data['event_id'],
'home_score': data['home_score'],
'away_score': data['away_score'],
'timestamp': data['timestamp']
})
# Process completed event
process_completed_event(data)
elif data['event_type'] == 'odds_updated':
# Handle odds changes
update_odds_cache(data['event_id'], data['odds'])
return {'status': 'received'}, 200
def process_completed_event(event_data):
"""Process completed event data"""
print(f"Event {event_data['event_id']} completed")
print(f"Final score: {event_data['home_score']}-{event_data['away_score']}")
# Update your betting platform
# Settle bets, update records, etc.
def update_odds_cache(event_id, new_odds):
"""Update cached odds data"""
print(f"Odds updated for event {event_id}")
# Update your odds cache
# Recalculate best odds, etc.
if __name__ == '__main__':
app.run(port=5000)Batch Processing
Handle large datasets efficiently:
def batch_process_leagues(client, batch_size=50):
"""Process leagues in batches to avoid memory issues"""
offset = 0
all_processed_data = []
while True:
# Get batch of leagues
try:
response = client._request('GET', '/v1/leagues', params={
'limit': batch_size,
'offset': offset
})
leagues = response['data']
if not leagues:
break # No more data
# Process this batch
batch_results = []
for league_data in leagues:
league = League(**league_data)
# Perform your processing
processed_league = {
'id': league.league_id,
'name': league.league_name,
'compliance_score': league.compliance_score,
'processed_at': datetime.now().isoformat()
}
batch_results.append(processed_league)
all_processed_data.extend(batch_results)
print(f"Processed batch {offset//batch_size + 1}: {len(batch_results)} leagues")
offset += batch_size
# Rate limiting
time.sleep(0.1)
except Exception as e:
print(f"Error processing batch at offset {offset}: {e}")
break
return all_processed_data
# Usage
all_league_data = batch_process_leagues(client)
print(f"Total processed: {len(all_league_data)} leagues")Error Handling & Resilience
import logging
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from altsportsleagues import AltSportsLeaguesError, RateLimitError
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=4, max=60),
retry=retry_if_exception_type((AltSportsLeaguesError, RateLimitError))
)
def resilient_api_call(client, method_name, *args, **kwargs):
"""Make API calls with automatic retry and proper error handling"""
method = getattr(client, method_name)
try:
result = method(*args, **kwargs)
logger.info(f"Successfully called {method_name}")
return result
except RateLimitError as e:
logger.warning(f"Rate limited on {method_name}, retrying: {e}")
if hasattr(e, 'retry_after'):
time.sleep(e.retry_after)
raise # Let tenacity handle retry
except AltSportsLeaguesError as e:
logger.error(f"API error on {method_name}: {e}")
raise
except Exception as e:
logger.error(f"Unexpected error on {method_name}: {e}")
raise
# Usage
try:
leagues = resilient_api_call(client, 'get_leagues')
events = resilient_api_call(client, 'get_events', league_id='nba', limit=100)
except Exception as e:
logger.error(f"Failed after retries: {e}")
# Implement fallback logic
leagues = get_cached_leagues()π§ͺ Testing
Unit Testing with the SDK
import pytest
from unittest.mock import Mock, patch
from altsportsleagues import AltSportsLeagues
class TestLeagueIntegration:
def setup_method(self):
self.client = AltSportsLeagues(api_key="test_key")
def test_get_leagues_success(self):
"""Test successful league retrieval"""
mock_response = {
'data': [
{
'league_id': 'nba',
'league_name': 'NBA',
'sport_bucket': 'team',
'compliance_score': 95
}
]
}
with patch.object(self.client.session, 'request') as mock_request:
mock_request.return_value.json.return_value = mock_response
leagues = self.client.get_leagues()
assert len(leagues) == 1
assert leagues[0].league_name == 'NBA'
assert leagues[0].compliance_score == 95
def test_get_leagues_api_error(self):
"""Test API error handling"""
with patch.object(self.client.session, 'request') as mock_request:
mock_request.return_value.raise_for_status.side_effect = Exception("API Error")
with pytest.raises(AltSportsLeaguesError):
self.client.get_leagues()
def test_rate_limit_handling(self):
"""Test rate limit error handling"""
with patch.object(self.client.session, 'request') as mock_request:
from requests.exceptions import HTTPError
response_mock = Mock()
response_mock.status_code = 429
response_mock.json.return_value = {'message': 'Rate limit exceeded'}
error = HTTPError()
error.response = response_mock
mock_request.return_value.raise_for_status.side_effect = error
with pytest.raises(RateLimitError):
self.client.get_leagues()Integration Testing
import pytest
import os
@pytest.fixture
def real_client():
"""Fixture for real API client (requires API key)"""
api_key = os.getenv('ALTSPORTSLEAGUES_API_KEY')
if not api_key:
pytest.skip("ALTSPORTSLEAGUES_API_KEY not set")
return AltSportsLeagues(api_key=api_key)
class TestRealAPIIntegration:
def test_leagues_endpoint(self, real_client):
"""Test real leagues endpoint"""
leagues = real_client.get_leagues()
assert isinstance(leagues, list)
if leagues:
league = leagues[0]
assert hasattr(league, 'league_id')
assert hasattr(league, 'league_name')
assert hasattr(league, 'sport_bucket')
def test_events_endpoint(self, real_client):
"""Test real events endpoint"""
events = real_client.get_events(limit=5)
assert isinstance(events, list)
assert len(events) <= 5
if events:
event = events[0]
assert hasattr(event, 'event_id')
assert hasattr(event, 'home_team')
assert hasattr(event, 'away_team')
def test_sports_endpoint(self, real_client):
"""Test sports endpoint"""
sports = real_client.get_sports()
assert isinstance(sports, list)
if sports:
sport = sports[0]
assert hasattr(sport, 'sport_id')
assert hasattr(sport, 'name')
assert hasattr(sport, 'bucket')π Monitoring & Analytics
API Usage Tracking
class APIUsageTracker:
"""Track API usage and costs"""
def __init__(self):
self.calls = []
self.costs = {
'get_leagues': 0.01,
'get_events': 0.02,
'get_odds': 0.05,
# Add other endpoints
}
def track_call(self, method_name, params=None):
"""Track an API call"""
call_info = {
'method': method_name,
'timestamp': datetime.now(),
'params': params or {},
'cost': self.costs.get(method_name, 0.01)
}
self.calls.append(call_info)
print(f"API Call: {method_name}, Cost: ${call_info['cost']}")
def get_usage_summary(self):
"""Get usage summary"""
total_calls = len(self.calls)
total_cost = sum(call['cost'] for call in self.calls)
# Calls by method
method_counts = {}
for call in self.calls:
method = call['method']
method_counts[method] = method_counts.get(method, 0) + 1
return {
'total_calls': total_calls,
'total_cost': total_cost,
'calls_by_method': method_counts,
'average_cost_per_call': total_cost / total_calls if total_calls > 0 else 0
}
# Usage tracking
tracker = APIUsageTracker()
# Monkey patch client methods to track usage
original_get_leagues = client.get_leagues
def tracked_get_leagues(*args, **kwargs):
tracker.track_call('get_leagues', kwargs)
return original_get_leagues(*args, **kwargs)
client.get_leagues = tracked_get_leagues
# Use client normally
leagues = client.get_leagues()
# Get usage summary
summary = tracker.get_usage_summary()
print(f"Total API calls: {summary['total_calls']}")
print(f"Total cost: ${summary['total_cost']:.3f}")π― Best Practices
Performance Optimization
- Caching: Cache frequently accessed data
- Batching: Use batch operations for multiple items
- Rate Limiting: Respect API rate limits
- Async: Use async operations for high-throughput applications
Error Handling
- Retry Logic: Implement exponential backoff for transient errors
- Circuit Breakers: Fail fast during outages
- Fallbacks: Have backup data sources
- Logging: Comprehensive error logging
Security
- API Keys: Never commit API keys to code
- Environment Variables: Use environment variables for configuration
- HTTPS: Always use HTTPS in production
- Validation: Validate all input data
π Support & Troubleshooting
Common Issues
Authentication Errors
# Check API key
print(f"API Key configured: {bool(client.api_key)}")
# Test authentication
try:
client.ping()
print("Authentication successful")
except AuthenticationError:
print("Authentication failed - check API key")Rate Limiting
# Check rate limit headers
response = client.session.get(f"{client.base_url}/health")
print(f"Rate limit remaining: {response.headers.get('X-RateLimit-Remaining')}")
print(f"Rate limit reset: {response.headers.get('X-RateLimit-Reset')}")Timeout Issues
# Increase timeout for slow operations
client = AltSportsLeagues(
api_key="your_key",
timeout=60 # 60 seconds
)Support Resources
- API Documentation: api.altsportsleagues.ai (opens in a new tab)
- SDK Reference: docs.altsportsleagues.ai/sdk (opens in a new tab)
- Community Forum: community.altsportsleagues.ai (opens in a new tab)
- GitHub Issues: github.com/altsportsleagues/python-sdk/issues (opens in a new tab)
Ready to build with AltSportsLeagues.ai? Get your API key today (opens in a new tab)!