SportsGameOdds SDK Guide
While you can always make requests to the API directly, using our SDKs is an easy way to get started. Here you’ll learn how to install, configure, and use our SDK across multiple programming languages with real-world examples.
All code examples shown in this guide are available in the relevant SportsGameOdds GitHub repositories.
Installation
Install the SDK using your language’s package manager:
# Using npm
npm install sports-odds-api
# Using yarn
yarn add sports-odds-api
# Using pnpm
pnpm add sports-odds-api# Using pip
pip install sports-odds-api
# Using poetry
poetry add sports-odds-api# Using bundler
bundle add sports-odds-api
# Or add to Gemfile
gem "sports-odds-api", "~> 1.0"go get github.com/SportsGameOdds/sports-odds-api-go// Maven (pom.xml)
<dependency>
<groupId>com.sportsgameodds.api</groupId>
<artifactId>sports-odds-api</artifactId>
<version>1.0.0</version>
</dependency>
// Gradle (build.gradle)
implementation 'com.sportsgameodds.api:sports-odds-api:1.0.0'Quick Start
Get up and running in under 60 seconds:
import SportsGameOdds from "sports-odds-api";
const client = new SportsGameOdds({
apiKeyHeader: process.env.SPORTS_ODDS_API_KEY_HEADER,
});
// Fetch first page of events
const page = await client.events.get({ limit: 5 });
console.log(`Found ${page.data.length} events`);
// Access event data
const event = page.data[0];
console.log(`Event: ${event.teams.away.name} @ ${event.teams.home.name}`);import os
from sports_odds_api import SportsGameOdds
client = SportsGameOdds(
api_key_param=os.environ.get("SPORTS_ODDS_API_KEY_HEADER")
)
# Fetch first page of events
page = client.events.get(limit=5)
print(f"Found {len(page.data)} events")
# Access event data
event = page.data[0]
print(f"Event: {event.teams.away.name} @ {event.teams.home.name}")require "sports_odds_api"
client = SportsOddsAPI::Client.new(
api_key_param: ENV["SPORTS_ODDS_API_KEY_HEADER"]
)
# Fetch first page of events
page = client.events.get(limit: 5)
puts "Found #{page.data.length} events"
# Access event data
event = page.data[0]
puts "Event: #{event.teams.away.name} @ #{event.teams.home.name}"package main
import (
"context"
"fmt"
"os"
sportsoddsapi "github.com/SportsGameOdds/sports-odds-api-go"
"github.com/SportsGameOdds/sports-odds-api-go/option"
)
func main() {
client := sportsoddsapi.NewClient(
option.WithAPIKeyParam(os.Getenv("SPORTS_ODDS_API_KEY_HEADER")),
)
// Fetch first page of events
ctx := context.Background()
page, _ := client.Events.Get(ctx, sportsoddsapi.EventGetParams{
Limit: sportsoddsapi.Float(5),
})
fmt.Printf("Found %d events\n", len(page.Data))
// Access event data
event := page.Data[0]
fmt.Printf("Event: %s @ %s\n",
event.Teams.Away.Name, event.Teams.Home.Name)
}import com.sportsgameodds.api.client.SportsGameOddsClient;
import com.sportsgameodds.api.client.okhttp.SportsGameOddsOkHttpClient;
import com.sportsgameodds.api.models.events.EventGetPage;
import com.sportsgameodds.api.models.events.EventGetParams;
public class QuickStart {
public static void main(String[] args) {
SportsGameOddsClient client = SportsGameOddsOkHttpClient.builder()
.apiKeyHeader(System.getenv("SPORTS_ODDS_API_KEY_HEADER"))
.build();
// Fetch first page of events
EventGetParams request = EventGetParams.builder()
.limit(5.0)
.build();
EventGetPage page = client.events().get(request);
System.out.println("Found " + page.items().size() + " events");
// Access event data
page.items().get(0).teams().ifPresent(teams -> {
System.out.println("Event: " +
teams.away().name().orElse("N/A") + " @ " +
teams.home().name().orElse("N/A"));
});
}
}Complete Examples
View complete working examples in our GitHub repositories:
Pagination
The SportsGameOdds API returns data in pages to ensure optimal performance. Our SDKs provide both automatic and manual pagination options.
Auto-Pagination
The easiest way to iterate through all results is using auto-pagination, which automatically fetches subsequent pages as you iterate:
// Iterate through all events using async iteration
for await (const event of client.events.get({ limit: 100 })) {
console.log(`${event.eventID}: ${event.activity}`);
// Process each event
// SDK automatically fetches next page when needed
}# Sync auto-pagination
for event in client.events.get(limit=100).auto_paging_iter():
print(f"{event.eventID}: {event.activity}")
# SDK automatically fetches next page when needed
# Async auto-pagination
async for event in client.events.get(limit=100).auto_paging_iter():
print(f"{event.eventID}: {event.activity}")# Auto-pagination with block
page = client.events.get(limit: 100)
page.auto_paging_each do |event|
puts "#{event.event_id}: #{event.activity}"
# SDK automatically fetches next page when needed
end// Auto-pagination with iterator
iter := client.Events.GetAutoPaging(ctx, sportsoddsapi.EventGetParams{
Limit: sportsoddsapi.Float(100),
})
for iter.Next() {
event := iter.Current()
fmt.Printf("%s: %s\n", event.EventID, event.Activity)
// SDK automatically fetches next page when needed
}
if err := iter.Err(); err != nil {
// Handle error
}// Note: Java SDK currently supports manual pagination
// See manual pagination example below
EventGetParams request = EventGetParams.builder()
.limit(100.0)
.build();
EventGetPage page = client.events().get(request);
for (Event event : page.items()) {
System.out.println(event.eventId().orElse("") + ": " +
event.activity().orElse(""));
}Manual Pagination
For more control over pagination, you can manually navigate through pages:
let page = await client.events.get({ limit: 100 });
// Process first page
console.log(`Page 1: ${page.data.length} events`);
// Check if there are more pages
while (page.hasNextPage()) {
page = await page.getNextPage();
console.log(`Next page: ${page.data.length} events`);
}page = client.events.get(limit=100)
# Process first page
print(f"Page 1: {len(page.data)} events")
# Check if there are more pages
while page.has_next_page():
page = page.get_next_page()
print(f"Next page: {len(page.data)} events")page = client.events.get(limit: 100)
# Process first page
puts "Page 1: #{page.data.length} events"
# Check if there are more pages
while page.next_page?
page = page.next_page
puts "Next page: #{page.data.length} events"
endpage, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{
Limit: sportsoddsapi.Float(100),
})
if err != nil {
// Handle error
}
// Process first page
fmt.Printf("Page 1: %d events\n", len(page.Data))
// Navigate through pages manually
for {
nextPage, err := page.GetNextPage()
if err != nil || nextPage == nil {
break
}
page = nextPage
fmt.Printf("Next page: %d events\n", len(page.Data))
}EventGetParams request = EventGetParams.builder()
.limit(100.0)
.build();
EventGetPage page = client.events().get(request);
// Process first page
System.out.println("Page 1: " + page.items().size() + " events");
// Navigate through pages using cursor
while (page.nextCursor().isPresent()) {
EventGetParams nextRequest = EventGetParams.builder()
.limit(100.0)
.cursor(page.nextCursor().get())
.build();
page = client.events().get(nextRequest);
System.out.println("Next page: " + page.items().size() + " events");
}Filtering and Query Parameters
Filter events by league, date, odds availability, and more using query parameters:
// Filter NFL events with available odds
const nflEvents = await client.events.get({
leagueID: "NFL",
oddsAvailable: true,
finalized: false,
limit: 50,
});
console.log(`Found ${nflEvents.data.length} NFL events with odds`);
// Filter events by specific event IDs
const specificEvents = await client.events.get({
eventIDs: "1234567890,0987654321",
});# Filter NFL events with available odds
nfl_events = client.events.get(
leagueID='NFL',
oddsAvailable=True,
finalized=False,
limit=50
)
print(f"Found {len(nfl_events.data)} NFL events with odds")
# Filter events by specific event IDs
specific_events = client.events.get(
eventIDs='1234567890,0987654321'
)# Filter NFL events with available odds
nfl_events = client.events.get(
leagueID: 'NFL',
oddsAvailable: true,
finalized: false,
limit: 50
)
puts "Found #{nfl_events.data.length} NFL events with odds"
# Filter events by specific event IDs
specific_events = client.events.get(
eventIDs: '1234567890,0987654321'
)// Filter NFL events with available odds
nflEvents, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{
LeagueID: sportsoddsapi.String("NFL"),
OddsAvailable: sportsoddsapi.Bool(true),
Finalized: sportsoddsapi.Bool(false),
Limit: sportsoddsapi.Float(50),
})
if err == nil {
fmt.Printf("Found %d NFL events with odds\n", len(nflEvents.Data))
}
// Filter events by specific event IDs
specificEvents, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{
EventIDs: sportsoddsapi.String("1234567890,0987654321"),
})// Filter NFL events with available odds
EventGetParams request = EventGetParams.builder()
.leagueId("NFL")
.oddsAvailable(true)
.finalized(false)
.limit(50.0)
.build();
EventGetPage nflEvents = client.events().get(request);
System.out.println("Found " + nflEvents.items().size() + " NFL events with odds");
// Filter events by specific event IDs
EventGetParams specificRequest = EventGetParams.builder()
.eventIds("1234567890,0987654321")
.build();
EventGetPage specificEvents = client.events().get(specificRequest);Available Filters
Common query parameters include:
leagueID- Filter by league (e.g., ‘NFL’, ‘NBA’, ‘MLB’)eventIDs- Comma-separated list of specific event IDsoddsAvailable- Only return events with odds datalive- Filter by live statusfinalized- Filter by finalized statuslimit- Number of results per page (default: 100, max: 500)
See the API Reference for a complete list of available parameters.
Error Handling
Handle API errors gracefully with proper exception handling:
import SportsGameOdds from "sports-odds-api";
try {
const page = await client.events.get();
console.log(`Successfully fetched ${page.data.length} events`);
} catch (err) {
if (err instanceof SportsGameOdds.APIError) {
console.error("API Error:", {
status: err.status,
message: err.message,
headers: err.headers,
});
} else {
console.error("Unexpected error:", err);
}
}from sports_odds_api import SportsGameOdds
from sports_odds_api.errors import (
APIError,
AuthenticationError,
APIStatusError,
RateLimitError,
)
try:
page = client.events.get()
print(f"Successfully fetched {len(page.data)} events")
except AuthenticationError as e:
print(f"Authentication failed: {e}")
except RateLimitError as e:
print(f"Rate limit exceeded: {e}")
except APIStatusError as e:
print(f"API error {e.status_code}: {e.message}")
except APIError as e:
print(f"API error: {e}")require "sports_odds_api"
begin
page = client.events.get
puts "Successfully fetched #{page.data.length} events"
rescue SportsOddsAPI::Errors::AuthenticationError => e
puts "Authentication failed: #{e.message}"
rescue SportsOddsAPI::Errors::RateLimitError => e
puts "Rate limit exceeded: #{e.message}"
rescue SportsOddsAPI::Errors::NotFoundError => e
puts "Resource not found: #{e.message}"
rescue SportsOddsAPI::Errors::APIError => e
puts "API error: #{e.message}"
endimport (
"errors"
"fmt"
sportsoddsapi "github.com/SportsGameOdds/sports-odds-api-go"
)
page, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{})
if err != nil {
// Check for specific error types
var apiErr *sportsoddsapi.Error
if errors.As(err, &apiErr) {
fmt.Printf("API Error %d: %s\n", apiErr.StatusCode, apiErr.Message)
} else {
fmt.Printf("Unexpected error: %v\n", err)
}
return
}
fmt.Printf("Successfully fetched %d events\n", len(page.Data))import com.sportsgameodds.api.errors.SportsGameOddsException;
try {
EventGetPage page = client.events().get();
System.out.println("Successfully fetched " + page.items().size() + " events");
} catch (SportsGameOddsException e) {
System.err.println("API Error: " + e.getMessage());
// Access additional error details if available
if (e.statusCode().isPresent()) {
System.err.println("Status Code: " + e.statusCode().get());
}
} catch (Exception e) {
System.err.println("Unexpected error: " + e.getMessage());
}Common Error Types
- AuthenticationError (401) - Invalid or missing API key
- PermissionDeniedError (403) - Feature not available on your plan
- NotFoundError (404) - Resource not found
- RateLimitError (429) - Rate limit exceeded
- APIStatusError (5xx) - Server error
Timeout and Retry Configuration
Configure timeouts and retry behavior for robust applications:
// Global configuration (applies to all requests)
const client = new SportsGameOdds({
apiKeyHeader: process.env.SPORTS_ODDS_API_KEY_HEADER,
timeout: 20 * 1000, // 20 seconds
maxRetries: 3, // Retry up to 3 times
});
// Per-request configuration (overrides global settings)
const page = await client.events.get({
limit: 100,
timeout: 5 * 1000, // 5 seconds for this request
maxRetries: 1, // Retry once for this request
});import httpx
# Global configuration (applies to all requests)
client = SportsGameOdds(
api_key_param=os.environ.get("SPORTS_ODDS_API_KEY_HEADER"),
timeout=httpx.Timeout(20.0), # 20 seconds
max_retries=3, # Retry up to 3 times
)
# Per-request configuration
page = client.events.get(
limit=100,
timeout=5.0, # 5 seconds for this request
)# Global configuration (applies to all requests)
client = SportsOddsAPI::Client.new(
api_key_param: ENV["SPORTS_ODDS_API_KEY_HEADER"],
timeout: 20, # 20 seconds
max_retries: 3, # Retry up to 3 times
)
# Configuration applies to all requests from this client
page = client.events.get(limit: 100)import (
"context"
"time"
"github.com/SportsGameOdds/sports-odds-api-go/option"
)
// Global configuration
client := sportsoddsapi.NewClient(
option.WithAPIKeyParam(os.Getenv("SPORTS_ODDS_API_KEY_HEADER")),
option.WithMaxRetries(3),
)
// Per-request timeout using context
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
page, err := client.Events.Get(
ctx,
sportsoddsapi.EventGetParams{Limit: sportsoddsapi.Float(100)},
option.WithRequestTimeout(5*time.Second),
)import java.time.Duration;
// Global configuration
SportsGameOddsClient client = SportsGameOddsOkHttpClient.builder()
.apiKeyHeader(System.getenv("SPORTS_ODDS_API_KEY_HEADER"))
.timeout(Duration.ofSeconds(20))
.maxRetries(3)
.build();
// Configuration applies to all requests
EventGetParams request = EventGetParams.builder()
.limit(100.0)
.build();
EventGetPage page = client.events().get(request);Best Practices
- Set reasonable timeouts to avoid hanging requests
- Configure retries for transient network issues
- Use shorter timeouts for time-sensitive operations
- Monitor retry counts in production
Working with Odds Data
Access and parse odds data efficiently:
// Fetch events with odds
const events = await client.events.get({
leagueID: "NFL",
oddsAvailable: true,
limit: 10,
});
// Parse odds data
for (const event of events.data) {
console.log(`\nEvent: ${event.teams.away.name} @ ${event.teams.home.name}`);
if (event.odds) {
// Odds is an object keyed by oddID
for (const [oddID, odd] of Object.entries(event.odds)) {
console.log(` ${odd.betTypeID}: ${odd.bookmakerID}`);
// Access line and price data
if (odd.line) console.log(` Line: ${odd.line}`);
if (odd.price) console.log(` Price: ${odd.price}`);
}
}
}# Fetch events with odds
events = client.events.get(
leagueID='NFL',
oddsAvailable=True,
limit=10
)
# Parse odds data
for event in events.data:
print(f"\nEvent: {event.teams.away.name} @ {event.teams.home.name}")
if event.odds:
# Odds is a dict keyed by oddID
for odd_id, odd in event.odds.items():
print(f" {odd.betTypeID}: {odd.bookmakerID}")
# Access line and price data
if odd.line:
print(f" Line: {odd.line}")
if odd.price:
print(f" Price: {odd.price}")# Fetch events with odds
events = client.events.get(
leagueID: 'NFL',
oddsAvailable: true,
limit: 10
)
# Group odds by betTypeID for easier analysis
events.data.each do |event|
puts "\nEvent: #{event.teams.away.name} @ #{event.teams.home.name}"
next unless event.odds
# Group by bet type
odds_by_type = {}
event.odds.each do |odd_id, odd|
bet_type_id = odd.bet_type_id
odds_by_type[bet_type_id] ||= []
odds_by_type[bet_type_id] << odd
end
puts " Available bet types: #{odds_by_type.keys.join(', ')}"
puts " Total markets: #{event.odds.length}"
end// Fetch events with odds
events, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{
LeagueID: sportsoddsapi.String("NFL"),
OddsAvailable: sportsoddsapi.Bool(true),
Limit: sportsoddsapi.Float(10),
})
if err != nil {
// Handle error
}
// Parse odds data
for _, event := range events.Data {
fmt.Printf("\nEvent: %s @ %s\n",
event.Teams.Away.Name, event.Teams.Home.Name)
if event.Odds != nil {
// Odds is a map keyed by oddID
for oddID, odd := range event.Odds {
fmt.Printf(" %s: %s\n", odd.BetTypeID, odd.BookmakerID)
// Access line and price data
if odd.Line != nil {
fmt.Printf(" Line: %f\n", *odd.Line)
}
if odd.Price != nil {
fmt.Printf(" Price: %d\n", *odd.Price)
}
}
}
}// Fetch events with odds
EventGetParams request = EventGetParams.builder()
.leagueId("NFL")
.oddsAvailable(true)
.limit(10.0)
.build();
EventGetPage events = client.events().get(request);
// Parse odds data
for (Event event : events.items()) {
event.teams().ifPresent(teams -> {
System.out.println("\nEvent: " +
teams.away().name().orElse("N/A") + " @ " +
teams.home().name().orElse("N/A"));
});
event.odds().ifPresent(odds -> {
// Odds contains additional properties as a Map
Map<String, JsonValue> oddsData = odds._additionalProperties();
System.out.println(" Total markets: " + oddsData.size());
// Parse each odd
oddsData.forEach((oddID, oddValue) -> {
// Access odd properties
System.out.println(" Market: " + oddID);
});
});
}Real-Time Streaming (AllStar Plan)
Subscribe to real-time updates using our streaming API (requires AllStar plan):
// Get stream connection info
const streamInfo = await client.stream.events({
feed: "events:live",
});
console.log("Stream channel:", streamInfo.channel);
console.log("Initial events:", streamInfo.data.length);
// Use Pusher client to connect to WebSocket
import Pusher from "pusher-js";
const pusher = new Pusher(streamInfo.pusherKey, {
cluster: streamInfo.pusherOptions.cluster,
});
const channel = pusher.subscribe(streamInfo.channel);
channel.bind("update", (data) => {
console.log("Event update:", data);
});# Get stream connection info
stream_info = client.stream.events(feed='events:live')
print(f"Stream channel: {stream_info.channel}")
print(f"Initial events: {len(stream_info.data)}")
# Use pusher client to connect to WebSocket
import pysher
pusher = pysher.Pusher(
stream_info.pusher_key,
cluster=stream_info.pusher_options['cluster']
)
def update_handler(data):
print(f"Event update: {data}")
pusher.connection.bind('pusher:connection_established',
lambda data: None)
pusher.subscribe(stream_info.channel).bind('update', update_handler)
pusher.connect()# Get stream connection info
stream_info = client.stream.events(feed: 'events:live')
puts "Stream channel: #{stream_info.channel}"
puts "Initial events: #{stream_info.data.length}"
# Use pusher client to connect to WebSocket
require 'pusher-client'
pusher = PusherClient::Socket.new(stream_info.pusher_key, {
cluster: stream_info.pusher_options['cluster']
})
pusher.subscribe(stream_info.channel)
pusher[stream_info.channel].bind('update') do |data|
puts "Event update: #{data}"
end
pusher.connect(true)// Get stream connection info
streamInfo, err := client.Stream.Events(ctx, sportsoddsapi.StreamEventsParams{
Feed: sportsoddsapi.String("events:live"),
})
if err != nil {
// Handle error (may be permission error if not on AllStar plan)
}
fmt.Printf("Stream channel: %s\n", streamInfo.Channel)
fmt.Printf("Initial events: %d\n", len(streamInfo.Data))
// Use Pusher client library to connect to WebSocket
// Implementation depends on chosen Go Pusher client library// Get stream connection info
StreamEventsParams request = StreamEventsParams.builder()
.feed("events:live")
.build();
StreamEventsResponse streamInfo = client.stream().events(request);
streamInfo.channel().ifPresent(channel ->
System.out.println("Stream channel: " + channel));
streamInfo.data().ifPresent(data ->
System.out.println("Initial events: " + data.size()));
// Use Pusher client library to connect to WebSocket
// Implementation depends on chosen Java Pusher client libraryAllStar Plan Required
Real-time streaming is only available on the AllStar plan. Requests will return a 403 Permission Denied error if not subscribed to the AllStar plan.
Type Safety and IDE Support
All SDKs provide full type definitions for excellent IDE autocomplete and type checking:
import SportsGameOdds from "sports-odds-api";
// Full TypeScript types available
const client = new SportsGameOdds({
apiKeyHeader: process.env.SPORTS_ODDS_API_KEY_HEADER,
});
// Type-safe event access with autocomplete
const page = await client.events.get();
const event: SportsGameOdds.Event = page.data[0];
// IDE autocomplete for all properties
console.log(event.eventID);
console.log(event.leagueID);
console.log(event.teams.away.name);
console.log(event.status.startsAt);from sports_odds_api import SportsGameOdds
from sports_odds_api.types import Event
client = SportsGameOdds(
api_key_param=os.environ.get("SPORTS_ODDS_API_KEY_HEADER")
)
# Type hints with Pydantic models
page = client.events.get()
event: Event = page.data[0]
# Convert to dict or JSON
event_dict = event.to_dict()
event_json = event.to_json()
# IDE autocomplete for all properties
print(event.eventID)
print(event.leagueID)
print(event.teams.away.name)require "sports_odds_api"
client = SportsOddsAPI::Client.new(
api_key_param: ENV["SPORTS_ODDS_API_KEY_HEADER"]
)
# Ruby objects with attribute accessors
page = client.events.get
event = page.data[0]
# Access properties with Ruby conventions
puts event.event_id
puts event.league_id
puts event.teams.away.name
puts event.status.starts_atimport sportsoddsapi "github.com/SportsGameOdds/sports-odds-api-go"
// Strongly typed structs
page, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{})
if err != nil {
// Handle error
}
event := page.Data[0]
// Compile-time type safety
fmt.Println(event.EventID)
fmt.Println(event.LeagueID)
fmt.Println(event.Teams.Away.Name)
fmt.Println(event.Status.StartsAt)import com.sportsgameodds.api.models.events.Event;
// Strongly typed with Optional support
EventGetPage page = client.events().get();
Event event = page.items().get(0);
// Type-safe access with Optional chaining
event.eventId().ifPresent(id -> System.out.println(id));
event.leagueId().ifPresent(league -> System.out.println(league));
event.teams().ifPresent(teams -> {
teams.away().name().ifPresent(name -> System.out.println(name));
});Advanced Usage
Accessing Raw Response Data
Sometimes you need access to the raw HTTP response:
// Get only the raw response
const response = await client.events.get().asResponse();
console.log("Status:", response.status);
console.log("Headers:", response.headers);
// Get both parsed data and raw response
const { data: page, response: raw } = await client.events.get().withResponse();
console.log(`Fetched ${page.data.length} events`);
console.log("Response status:", raw.status);# Python SDK returns parsed data by default
# Access response metadata through the client if needed
page = client.events.get()
print(f"Fetched {len(page.data)} events")# Ruby SDK returns parsed data by default
# Access response through the page object if available
page = client.events.get
puts "Fetched #{page.data.length} events"// Go SDK returns both data and error
page, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{})
if err != nil {
// Error contains HTTP status information if applicable
var apiErr *sportsoddsapi.Error
if errors.As(err, &apiErr) {
fmt.Printf("Status Code: %d\n", apiErr.StatusCode)
}
return
}
fmt.Printf("Fetched %d events\n", len(page.Data))// Java SDK returns parsed data
// Access response metadata through exceptions if needed
try {
EventGetPage page = client.events().get();
System.out.println("Fetched " + page.items().size() + " events");
} catch (SportsGameOddsException e) {
e.statusCode().ifPresent(code ->
System.out.println("Status Code: " + code));
}Concurrent Requests
Make multiple requests concurrently for better performance:
// Fetch multiple leagues concurrently
const [nflEvents, nbaEvents, mlbEvents] = await Promise.all([
client.events.get({ leagueID: "NFL", limit: 50 }),
client.events.get({ leagueID: "NBA", limit: 50 }),
client.events.get({ leagueID: "MLB", limit: 50 }),
]);
console.log(`NFL: ${nflEvents.data.length} events`);
console.log(`NBA: ${nbaEvents.data.length} events`);
console.log(`MLB: ${mlbEvents.data.length} events`);import asyncio
# Async concurrent requests
async def fetch_all_leagues():
async with SportsGameOdds(
api_key_param=os.environ.get("SPORTS_ODDS_API_KEY_HEADER")
) as client:
nfl, nba, mlb = await asyncio.gather(
client.events.get(leagueID='NFL', limit=50),
client.events.get(leagueID='NBA', limit=50),
client.events.get(leagueID='MLB', limit=50),
)
print(f"NFL: {len(nfl.data)} events")
print(f"NBA: {len(nba.data)} events")
print(f"MLB: {len(mlb.data)} events")
asyncio.run(fetch_all_leagues())require 'concurrent'
# Create concurrent requests using threads
futures = [
Concurrent::Future.execute {
client.events.get(leagueID: 'NFL', limit: 50)
},
Concurrent::Future.execute {
client.events.get(leagueID: 'NBA', limit: 50)
},
Concurrent::Future.execute {
client.events.get(leagueID: 'MLB', limit: 50)
}
]
# Wait for all to complete
nfl_events, nba_events, mlb_events = futures.map(&:value)
puts "NFL: #{nfl_events.data.length} events"
puts "NBA: #{nba_events.data.length} events"
puts "MLB: #{mlb_events.data.length} events"import (
"golang.org/x/sync/errgroup"
)
// Concurrent requests with errgroup
g, ctx := errgroup.WithContext(context.Background())
var nflEvents, nbaEvents, mlbEvents *sportsoddsapi.EventGetPage
g.Go(func() error {
page, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{
LeagueID: sportsoddsapi.String("NFL"),
Limit: sportsoddsapi.Float(50),
})
nflEvents = page
return err
})
g.Go(func() error {
page, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{
LeagueID: sportsoddsapi.String("NBA"),
Limit: sportsoddsapi.Float(50),
})
nbaEvents = page
return err
})
g.Go(func() error {
page, err := client.Events.Get(ctx, sportsoddsapi.EventGetParams{
LeagueID: sportsoddsapi.String("MLB"),
Limit: sportsoddsapi.Float(50),
})
mlbEvents = page
return err
})
if err := g.Wait(); err != nil {
// Handle error
}
fmt.Printf("NFL: %d events\n", len(nflEvents.Data))
fmt.Printf("NBA: %d events\n", len(nbaEvents.Data))
fmt.Printf("MLB: %d events\n", len(mlbEvents.Data))import java.util.concurrent.*;
// Concurrent requests with ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(3);
Future<EventGetPage> nflFuture = executor.submit(() ->
client.events().get(EventGetParams.builder()
.leagueId("NFL").limit(50.0).build()));
Future<EventGetPage> nbaFuture = executor.submit(() ->
client.events().get(EventGetParams.builder()
.leagueId("NBA").limit(50.0).build()));
Future<EventGetPage> mlbFuture = executor.submit(() ->
client.events().get(EventGetParams.builder()
.leagueId("MLB").limit(50.0).build()));
// Wait for all to complete
EventGetPage nflEvents = nflFuture.get();
EventGetPage nbaEvents = nbaFuture.get();
EventGetPage mlbEvents = mlbFuture.get();
System.out.println("NFL: " + nflEvents.items().size() + " events");
System.out.println("NBA: " + nbaEvents.items().size() + " events");
System.out.println("MLB: " + mlbEvents.items().size() + " events");
executor.shutdown();Example Projects
All examples shown in this guide are available as complete, runnable projects in our GitHub repositories:
TypeScript
- Repository: sports-odds-api-typescript
- Examples: View all TypeScript examples
Python
- Repository: sports-odds-api-python
- Examples: View all Python examples
Ruby
- Repository: sports-odds-api-ruby
- Examples: View all Ruby examples
Go
- Repository: sports-odds-api-go
- Examples: View all Go examples
Java
- Repository: sports-odds-api-java
- Examples: View all Java examples
Next Steps
Now that you understand how to use the SDK, explore these resources:
- API Reference - Complete API endpoint documentation
- Getting Started Guide - Reference back to core concepts
- Rate Limits - Understand rate limiting and best practices
