TUTORIAL

How to Get Football Data with Ruby - Complete API Tutorial

Step-by-step Ruby tutorial for fetching football fixtures, match stats and odds via API using net/http. Working code examples you can copy into Rails.

4 min read

Ruby and Rails are a productive choice for football data products, dashboards, and internal tools. TheStatsAPI is a plain REST JSON API, so the standard net/http and json libraries are all you need - no gem required.

This tutorial shows how to fetch football data with Ruby: competitions, fixtures, pagination, match stats, and odds.

Prerequisites

You need:

  • Ruby 3.0+
  • A TheStatsAPI API key

Set your API key as an environment variable:

export THESTATSAPI_KEY="your_api_key"

If you do not have a key yet, sign up at thestatsapi.com for a 7-day free trial.

Create a Small API Client

Create football_api.rb:

require "net/http"
require "json"
require "uri"

BASE_URL = "https://api.thestatsapi.com/api"

def tsapi_get(endpoint, params = {})
  uri = URI("#{BASE_URL}#{endpoint}")
  uri.query = URI.encode_www_form(params) unless params.empty?

  request = Net::HTTP::Get.new(uri)
  request["Authorization"] = "Bearer #{ENV.fetch('THESTATSAPI_KEY')}"
  request["Accept"] = "application/json"

  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
    http.request(request)
  end

  raise "API request failed: HTTP #{response.code}" if response.code.to_i >= 400

  JSON.parse(response.body)
end

URI.encode_www_form handles URL-encoding. Every example below reuses tsapi_get.

Fetch Competitions

require_relative "football_api"

result = tsapi_get("/football/competitions", { search: "Premier League" })

result["data"].each do |competition|
  puts "#{competition['id']} #{competition['name']} #{competition['country']}"
end

Typical output:

comp_3039 Premier League England

Save the competition ID for match and season queries.

Get Fixtures for a League

require_relative "football_api"

result = tsapi_get("/football/matches", {
  competition_id: "comp_3039",
  per_page: 10
})

result["data"].each do |match|
  home = match["home_team"]["name"]
  away = match["away_team"]["name"]
  puts "#{match['utc_date']} - #{home} vs #{away} (#{match['status']})"
end

Add date_from, date_to, season_id, team_id, and status to filter. See the fixtures API.

Handle Pagination

List endpoints return a meta block with total_pages.

require_relative "football_api"

def tsapi_get_all(endpoint, params = {})
  page = 1
  rows = []

  loop do
    result = tsapi_get(endpoint, params.merge(page: page))
    rows.concat(result["data"])

    total_pages = result.dig("meta", "total_pages") || 1
    break if page >= total_pages

    page += 1
  end

  rows
end

matches = tsapi_get_all("/football/matches", { competition_id: "comp_3039" })
puts "Fetched #{matches.length} matches"

For Rails apps, run this in a background job (Sidekiq, GoodJob) and cache rows in your database.

Get Match Stats

require_relative "football_api"

data = tsapi_get("/football/matches/mt_010249745/stats")["data"]
overview = data["overview"]

xg = overview["expected_goals"]["all"]
shots = overview["total_shots"]["all"]

puts "Shots: #{shots['home']} - #{shots['away']}"
puts "xG: #{xg['home']} - #{xg['away']}"

See the match stats API and xG API.

Get Pre-Match Odds

require_relative "football_api"

data = tsapi_get("/football/matches/mt_010249745/odds")["data"]

data["bookmakers"].each do |book|
  match_odds = book.dig("markets", "match_odds")
  next unless match_odds

  puts "#{book['bookmaker']}: #{match_odds}"
end

Use /football/matches/{match_id}/odds/live for in-play odds. See the Football Odds API.

Use It Inside Rails

Wrap the helper in a service object and read the key from Rails credentials:

# app/services/football_api.rb
class FootballApi
  BASE_URL = "https://api.thestatsapi.com/api"

  def self.get(endpoint, params = {})
    uri = URI("#{BASE_URL}#{endpoint}")
    uri.query = URI.encode_www_form(params) unless params.empty?

    request = Net::HTTP::Get.new(uri)
    request["Authorization"] = "Bearer #{Rails.application.credentials.thestatsapi_key}"
    request["Accept"] = "application/json"

    response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
    JSON.parse(response.body)
  end
end

Production Tips

  • Store the API key in environment variables or Rails credentials, never in source.
  • Cache responses with Rails.cache or Redis to respect plan limits.
  • Use pagination for backfills inside background jobs.
  • Check availability flags such as xg_available and live_odds_available.

FAQ

Can I use Ruby with TheStatsAPI?

Yes. TheStatsAPI is a REST JSON API, so Ruby's standard net/http and json libraries work directly. The examples above also include a Rails service object.

Do I need a Ruby gem?

No. The standard library is enough. You can add a gem like httparty or faraday if you prefer, but it is not required.

How do I fetch football odds in Ruby?

Use /football/matches/{match_id}/odds for pre-match odds and /football/matches/{match_id}/odds/live for live odds where available.

How do I get xG data in Ruby?

Call /football/matches/{match_id}/stats and read overview.expected_goals.all for team xG.

Start building today

Ready to Power Your Sports App?

Start your 7-day free trial. All endpoints included on every plan.

Cancel anytime
7-day free trial
Setup in 5 minutes