Get started with BetML's sports analytics API in minutes. Our platform provides enterprise-grade sports analytics and machine learning capabilities through a simple, intuitive API.
Sign up for a BetML account and obtain your API key from the dashboard. Your API key is used to authenticate all requests and track your usage. Keep it secure and never share it publicly.
We provide official SDKs for Python and Node.js. Choose the one that best fits your tech stack:
# Python installation
pip install betml
# Node.js installation
npm install @betml/sdk
Here's a complete example showing how to fetch real-time odds and set up automated trading:
# Python Example
from betml import BetML
import logging
# Initialize client with logging
logging.basicConfig(level=logging.INFO)
client = BetML(api_key="your_api_key")
# Configure market preferences
client.configure({
"sports": ["NFL", "NBA", "MLB"],
"markets": ["spread", "moneyline", "totals"],
"update_interval": 1000 # ms
})
# Set up real-time odds monitoring
@client.on("odds_update")
async def handle_odds_update(data):
# Analyze the opportunity
analysis = await client.analyze_market({
"event_id": data.event_id,
"market_type": data.market_type,
"current_odds": data.odds
})
# Execute trade if confidence is high
if analysis.confidence > 0.85:
trade = await client.execute_trade({
"event_id": data.event_id,
"side": analysis.recommended_side,
"stake": calculate_kelly(analysis)
})
logging.info(f"Trade executed: {trade.id}")
# Start monitoring
client.connect()
BetML uses API keys for authentication. Your API key should be included in the Authorization header for all requests. We use industry-standard JWT tokens for WebSocket connections.
Include your API key in the Authorization header using the Bearer scheme:
curl -H "Authorization: Bearer your_api_key" \
https://api.betml.com/v1/odds
For WebSocket connections, first obtain a session token:
session = await client.create_session()
await client.connect(session_token=session.token)
Our WebSocket API provides real-time updates for odds, scores, and market movements. You can subscribe to specific markets and receive instant notifications about relevant changes.
odds_update
- Real-time odds changesscore_update
- Live game scoresmarket_update
- Market status changesposition_update
- Position value changes# Configure multiple stream handlers
from betml import BetML, MarketType
client = BetML(api_key="your_key")
@client.on("odds_update", markets=[MarketType.SPREAD, MarketType.TOTALS])
async def handle_odds(data):
if data.movement > 0.5: # Significant line movement
await analyze_opportunity(data)
@client.on("score_update")
async def handle_score(data):
if data.is_momentum_shift:
await adjust_positions(data)
# Custom error handling
@client.on_error
async def handle_error(error):
if error.is_connection_error:
await reconnect_with_backoff()
else:
log_error(error)
# Start streaming with configuration
await client.connect(
heartbeat_interval=30,
reconnect_attempts=3,
compression=True
)
Implement robust error handling to ensure your application can gracefully handle API issues, rate limits, and network problems.
BetMLAuthError
- Authentication issuesBetMLRateLimitError
- Rate limit exceededBetMLValidationError
- Invalid request dataBetMLAPIError
- General API errorsBetMLConnectionError
- Network/connection issuesfrom betml.exceptions import (
BetMLAuthError,
BetMLRateLimitError,
BetMLConnectionError
)
async def fetch_with_retry(client, market_id):
max_retries = 3
retry_count = 0
while retry_count < max_retries:
try:
return await client.get_market(market_id)
except BetMLRateLimitError as e:
# Handle rate limiting with exponential backoff
await asyncio.sleep(2 ** retry_count)
retry_count += 1
except BetMLAuthError:
# Authentication issues require immediate attention
await refresh_credentials()
retry_count += 1
except BetMLConnectionError:
# Network issues might be temporary
if retry_count < max_retries - 1:
await asyncio.sleep(1)
retry_count += 1
else:
raise # Re-raise if max retries reached
raise Exception("Max retries exceeded")
Understanding and properly handling rate limits is crucial for maintaining stable integration with our API.
Plan | Requests/min | Concurrent Connections |
---|---|---|
Free | 60 | 1 |
Pro | 300 | 5 |
Enterprise | Unlimited | Unlimited |
All API responses include rate limit information in the headers:
X-RateLimit-Limit
: Total requests allowedX-RateLimit-Remaining
: Requests remainingX-RateLimit-Reset
: Time until limit resets (seconds)X-RateLimit-Type
: Current rate limit tierfrom betml import BetML
import time
class RateLimitHandler:
def __init__(self):
self.remaining_calls = None
self.reset_time = None
async def make_request(self, client):
if self.should_wait():
wait_time = self.reset_time - time.time()
await asyncio.sleep(wait_time)
try:
response = await client.get_odds()
self.update_limits(response.headers)
return response
except BetMLRateLimitError as e:
self.remaining_calls = 0
self.reset_time = time.time() + e.retry_after
raise
def should_wait(self):
return (self.remaining_calls is not None and
self.remaining_calls <= 0 and
self.reset_time > time.time())
def update_limits(self, headers):
self.remaining_calls = int(headers['X-RateLimit-Remaining'])
self.reset_time = time.time() + int(headers['X-RateLimit-Reset'])
Understanding our data models is crucial for effectively working with the BetML API.
{
"event_id": "nfl_2025_sb_kc_sf",
"sport": "NFL",
"market_type": "spread",
"timestamp": "2025-01-19T20:30:00Z",
"odds": {
"home": {
"line": -3.5,
"price": -110
},
"away": {
"line": 3.5,
"price": -110
}
},
"metadata": {
"venue": "Allegiant Stadium",
"weather": {
"temp": 72,
"condition": "Clear"
}
}
}
{
"position_id": "pos_12345",
"market_id": "nfl_2025_sb_kc_sf",
"side": "home",
"stake": 1000.00,
"entry_odds": -110,
"current_odds": -105,
"pnl": {
"realized": 0.00,
"unrealized": 45.45
},
"status": "open",
"timestamp": "2025-01-19T20:35:00Z"
}