Skip to content

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:

bash
# Using npm
npm install sports-odds-api

# Using yarn
yarn add sports-odds-api

# Using pnpm
pnpm add sports-odds-api
bash
# Using pip
pip install sports-odds-api

# Using poetry
poetry add sports-odds-api
bash
# Using bundler
bundle add sports-odds-api

# Or add to Gemfile
gem "sports-odds-api", "~> 1.0"
bash
go get github.com/SportsGameOdds/sports-odds-api-go
groovy
// 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:

ts
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}`);
python
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}")
ruby
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}"
go
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)
}
java
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:

ts
// 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
}
python
# 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}")
ruby
# 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
go
// 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
}
java
// 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:

ts
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`);
}
python
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")
ruby
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"
end
go
page, 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))
}
java
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:

ts
// 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",
});
python
# 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'
)
ruby
# 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'
)
go
// 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"),
})
java
// 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 IDs
  • oddsAvailable - Only return events with odds data
  • live - Filter by live status
  • finalized - Filter by finalized status
  • limit - 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:

ts
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);
  }
}
python
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}")
ruby
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}"
end
go
import (
	"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))
java
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:

ts
// 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
});
python
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
)
ruby
# 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)
go
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),
)
java
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:

ts
// 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}`);
    }
  }
}
python
# 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}")
ruby
# 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
go
// 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)
			}
		}
	}
}
java
// 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):

ts
// 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);
});
python
# 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()
ruby
# 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)
go
// 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
java
// 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 library

AllStar 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:

ts
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);
python
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)
ruby
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_at
go
import 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)
java
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:

ts
// 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
# 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
# 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
// 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
// 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:

ts
// 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`);
python
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())
ruby
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"
go
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))
java
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

Python

Ruby

Go

Java

Next Steps

Now that you understand how to use the SDK, explore these resources:




Need Help?

FAQ · Email · Chat · Discord