Exploring referee data with Sportmonks football API and Clojure
Contents

Understanding referees in football

Referees are the primary enforcers of the rules in a football match. They are responsible for ensuring the game is played fairly, safely, and within the official laws of the sport. While they often go unnoticed when everything runs smoothly, referees are central to match integrity and discipline.

Who are referees?

A football referee is a licensed official appointed to supervise a game. They undergo rigorous training and certification, often progressing through local leagues to national and international levels. Some referees even officiate in prestigious tournaments like the FIFA World Cup and UEFA Champions League.

Core responsibilities of a referee

The main duties of a referee include:

Enforcing the rules: Interpreting and applying the Laws of the Game.
Controlling the match: Managing player behaviour, handling timekeeping, and maintaining order.
Making decisions: Awarding free kicks, penalties, goals, and issuing disciplinary cards (yellow/red).
Collaborating with assistants: Working closely with assistant referees (linesmen), the fourth official, and video assistant referees (VAR) to ensure accurate decisions.
Ensuring player safety: Halting play for injuries, dangerous conduct, or poor weather conditions.

Types of officials in a match

While the “referee” refers to the central figure on the pitch, they are part of a larger officiating team that may include:

– Assistant referees (2): Responsible for offsides and boundary decisions.
– Fourth official: Handles substitutions and technical area management.
– VAR team: Reviews major incidents using video replay.
– Additional assistant referees (used in some competitions): Positioned behind goals to monitor incidents in the penalty area.

Why referee data matters

Understanding a referee’s history and officiating style can be crucial for:

– Match previews and analysis: Some referees give more cards, allow physical play, or are stricter with dissent.
– Betting and odds models: Referee trends influence game flow and outcomes.
– Team strategy: Coaches may adapt tactics based on how a referee typically handles fouls or penalties.

With Sportmonks’ API, you can access detailed referee data, from biography to match statistics which opens the door to richer match analysis and smarter applications.

What is Clojure?

Clojure is a modern, functional, and expressive programming language that runs on the Java Virtual Machine (JVM). It’s a dialect of Lisp, one of the oldest families of programming languages, but reimagined for today’s performance demands and software practices.

Key features of Clojure

Clojure combines the simplicity of Lisp with the power of Java, resulting in a language that’s both elegant and practical. Some of its defining features include:

Functional-first: Clojure promotes immutability and pure functions by default, reducing side effects and making code easier to test and reason about.
Immutable data structures: Instead of changing data in place, Clojure encourages creating new versions of data, which helps prevent bugs and race conditions.
REPL-driven development: The interactive Read-Eval-Print Loop (REPL) enables live coding and experimentation. You can send code directly from your editor and see results instantly, perfect for quick prototyping and debugging.
Concise syntax: Clojure’s syntax is minimal and uniform. It uses prefix notation (also known as S-expressions) which is extremely powerful for manipulating code as data.
Full JVM interoperability: Clojure can call any Java method or use Java libraries, making it highly versatile for web development, data processing, or API integration.

Where Clojure is used

Clojure is widely used in industries that demand robustness, scalability, and reliability. Common use cases include:

Backend services and web APIs
Data pipelines and analytics
– Concurrency-heavy applications
– Domain-specific languages (DSLs)
Financial systems and startups that value fast iteration with strong stability

Why use Clojure for API integrations?

Powerful data handling: Clojure’s data literals (maps, vectors, sets) match JSON responses almost 1-to-1, making it easy to parse and transform API responses.
Concise and expressive: You can write fewer lines of code while maintaining clarity, especially when chaining HTTP calls and data transformations.
Rich ecosystem: Libraries like clj-http, cheshire, and compojure provide mature tools for making HTTP requests, handling JSON, and building web apps.

Chapter 1. Setting up your environment

Before diving into referee data with Clojure and the Sportmonks Football API, we need to set up a development environment that supports Clojure’s tooling and workflow. This chapter covers installing the language, creating a basic project, and preparing it to make HTTP requests and handle JSON.

1. Install Clojure

To write and run Clojure code, you’ll need:

Java (JDK 11 or higher): Download here or install via your OS package manager.
Clojure CLI tools: Follow the official installation guide: clojure.org/guides/install_clojure

To verify your setup:

clojure -Sdescribe

If installed correctly, it should print toolchain and JVM details.

2. Set up a project using deps.edn

Instead of using Leiningen (which is still valid), we’ll use the Clojure CLI with a deps.edn project structure. Create a folder:

mkdir sportmonks-clojure
cd sportmonks-clojure

Create a deps.edn file with the following content:

{:deps {org.clojure/clojure {:mvn/version "1.11.1"}
        clj-http/clj-http {:mvn/version "3.12.3"}
        cheshire/cheshire {:mvn/version "5.11.0"}}}

This sets up three dependencies:

clojure: The language itself
clj-http: For making HTTP requests
cheshire: For parsing JSON into Clojure maps

3. Add a source directory

Create a simple source file:

mkdir -p src/sportmonks
touch src/sportmonks/core.clj

Open src/sportmonks/core.clj and add:

(ns sportmonks.core
  (:require [clj-http.client :as client]
            [cheshire.core :as json]))

(defn -main []
  (println "Sportmonks Referee API with Clojure!"))

Run it using:

clojure -M -m sportmonks.core

It should print:

Sportmonks Referee API with Clojure!

4. Get your Sportmonks API token

To authenticate your API calls:
 – Log into my.sportmonks.com
– Navigate to the “API Tokens” section
– Copy your personal token

You’ll need this token in upcoming code snippets. For security, you can pass it as an environment variable or store it in a .env file (with a library like environ if you prefer).

5. Setting up environment variables

Instead of hardcoding the API token in your code, store it securely as an environment variable.

a) Define it in your terminal session:

export SPORTMONKS_API_TOKEN=your_token_here

To make this persistent, add it to your shell config (e.g., ~/.bashrc or ~/.zshrc).

b) Access it in Clojure:

(def api-token (System/getenv "SPORTMONKS_API_TOKEN"))

6. Choosing an IDE for Clojure development

For this project, we’d be using VScode

– Open the Extensions panel (Ctrl+Shift+X)
– Search and install Calva

Features include:

– Inline evaluation
– Autocompletion
– Syntax highlighting
– Integrated REPL experience

Chapter 2. Retrieving referee data using Clojure

Now that your environment is ready, it’s time to connect to Sportmonks’ Football API and fetch detailed data about a referee. We’ll use the endpoint to retrieve personal details, nationality, seasonal statistics, and information about the referee’s most recent fixture, all in a single response.

1. API endpoint overview

To get comprehensive referee information, we use:

GET https://api.sportmonks.com/v3/football/referees/{referee_id}

We’ll include additional data by appending parameters:

country: Referee’s nationality
statistics.details.type: Breakdown of actions like cards or penalties
statistics.season.league: League context for the season stats
latest.fixture.*: Details of the latest match officiated (scores, teams, statistics)

We’ll also add a filter to specify which season’s statistics we want:

&filters=refereeStatisticSeasons:{season_id}

Example full request:

https://api.sportmonks.com/v3/football/referees/15273
?include=country;statistics.details.type;statistics.season.league;latest.fixture.statistics;latest.fixture.participants;latest.fixture.league;latest.fixture.scores
&filters=refereeStatisticSeasons:23614

For this example, we’re getting information about referee Michael Oliver.

2. Writing the function in Clojure

In your src/sportmonks/core.clj, let’s add a function that fetches the referee data:

(ns sportmonks.core
  (:require [clj-http.client :as client]
            [cheshire.core :as json]))

(def api-token (System/getenv "SPORTMONKS_API_TOKEN"))
(def base-url "https://api.sportmonks.com/v3/football/referees")

(defn get-referee-data [referee-id season-id]
  (let [includes (str "country;"
                      "statistics.details.type;"
                      "statistics.season.league;"
                      "latest.fixture.statistics;"
                      "latest.fixture.participants;"
                      "latest.fixture.league;"
                      "latest.fixture.scores")
        url (str base-url "/" referee-id
                 "?api_token=" api-token
                 "&include=" includes
                 "&filters=refereeStatisticSeasons:" season-id)
        response (client/get url {:as :json})]
    (:body response)))

(def referee-id 15273)
(def season-id 23614)

(def referee-data (get-referee-data referee-id season-id))

;; Helper to extract nested count by type_id
(defn get-count-by-type-id [details type-id]
  (some (fn [d]
          (when (= (:type_id d) type-id)
            (get-in d [ :value :all :count])))
        details))

(defn print-referee-summary [ref-data]
  (let [ref (:data ref-data)
        name (:name ref)
        country (get-in ref [:country :name])
        statistics (:statistics ref)
        stat-details (get-in statistics [0 :details])
        total-matches (get-count-by-type-id stat-details 188) ; Matches
        yellow-cards (get-count-by-type-id stat-details 83)
        red-cards (get-count-by-type-id stat-details 84)
        penalties (get-count-by-type-id stat-details 47)
        league-name (get-in statistics [0 :season :league :name])
        season-name (get-in statistics [0 :season :name])
        last-fixture (first (:latest ref))
        last-match-name (get-in last-fixture [:fixture :name])
        home-team (get-in last-fixture [:fixture :participants 0 :name])
        away-team (get-in last-fixture [:fixture :participants 1 :name])]

    (println "Name:" (or name "N/A"))
    (println "Country:" (or country "N/A"))
    (println "League:" (or league-name "N/A"))
    (println "Season:" (or season-name "N/A"))
    (println "Matches officiated this season:" (or total-matches "N/A"))
    (println "Yellow cards given:" (or yellow-cards "N/A"))
    (println "Red cards given:" (or red-cards "N/A"))
    (println "Penalties awarded:" (or penalties "N/A"))
    (println "Latest match:" (or last-match-name "N/A"))
    (println "Participants:" (str (or home-team "N/A") " vs " (or away-team "N/A")))))

(print-referee-summary referee-data)

What’s in the response?

You’ll receive a nested map with sections like:

– :name: Full name of the referee
– :country: A map with name, id, and image
– :statistics: Includes total matches, yellow/red cards, penalties, etc.
– :statistics.details: A breakdown by type (e.g. foul, penalty, yellow card)
– :statistics.season.league: League and season names
– :latest.fixture: The most recent game the referee officiated

Analyse referee trends with Sportmonks and clojure

Referee decisions shape every football match and now you can explore their patterns with precision. By combining Sportmonks’ football API with Clojure’s expressive tooling, you can retrieve rich referee profiles, match stats, and disciplinary trends to power smarter predictions and match previews.

Whether you’re building analytics tools, enhancing betting models, or adding depth to sports content, this integration helps you make data-driven decisions effortlessly.

Start your free trial today and bring referee intelligence into your Clojure applications.

FAQs

Why is analysing referee performance important in football?
Analysing referee performance is important because referees are the primary enforcers of rules, ensuring fairness and safety. Their officiating style (e.g., how strict they are with cards or fouls) can provide valuable insights for match previews, betting odds models, and even influence team strategies.
What kind of referee data does Sportmonks' football API offer?
Sportmonks' football API offers detailed data on referees, including their profiles (name, country), comprehensive match statistics (total matches officiated, yellow/red cards given, penalties awarded), and details about their latest officiated fixtures.
What is Clojure, and why is it recommended for API integrations like this?
Clojure is a modern, functional programming language that runs on the Java Virtual Machine (JVM). It's recommended for API integrations due to its powerful data handling capabilities (JSON responses map easily to Clojure's data structures), concise and expressive syntax, and a rich ecosystem of libraries for making HTTP requests and handling JSON.

Written by David Jaja

David Jaja is a technical content manager at Sportmonks, where he makes complex football data easier to understand for developers and businesses. With a background in frontend development and technical writing, he helps bridge the gap between technology and sports data. Through clear, insightful content, he ensures Sportmonks' APIs are accessible and easy to use, empowering developers to build standout football applications