# Leagues

> **Included in all plans**
>
> League data is available on all base plans (Starter, Growth, Pro, Enterprise). The number of leagues accessible varies by plan (5 leagues on Starter through all leagues on Enterprise).
>
> [Compare plans →](https://www.sportmonks.com/football-api/plans-pricing)

**Quick summary:** This tutorial covers the six league endpoints available in API v3. You'll learn how to retrieve your accessible leagues, filter by country or name, enrich responses with season data, and use the results as the foundation for fixture and standings queries.

**What you'll learn:**

* How to retrieve all leagues in your subscription and look up leagues by ID, country, name, and date
* How to enrich league responses with current season, upcoming, and latest fixtures
* How to use `select` to return only the fields your application needs
* How leagues fit into the wider API data hierarchy

**Time to complete:** 15 minutes **Skill level:** Beginner **Prerequisites:** [Authentication](https://docs.sportmonks.com/v3/welcome/authentication), [Includes](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes), [Filter and Select Fields](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/filter-and-select-fields)

### 1. When to use this feature

The leagues endpoint is typically the starting point for any football application. Each league belongs to a country and contains one or more seasons. League IDs are used as filter parameters throughout the API (in fixtures, standings, statistics, and more) so most integrations begin by fetching the list of accessible leagues.

#### Real-world use cases

* **Use case 1: Building a league selector** At startup, your app fetches all leagues in the subscription to populate a dropdown or navigation. You display league names, logos, and optionally their current season for context.
* **Use case 2: Country-filtered league listing** Your product is focused on a single country (e.g. Scotland). GET Leagues by Country ID returns only the leagues for that country, avoiding the need to filter client-side.
* **Use case 3: Discovering leagues with active matches right now** You're building a live scores section. GET Leagues by Live returns only the leagues that have fixtures currently in play, so you can show a relevant selection without polling every league separately.
* **Use case 4: Fetching the current season ID for fixtures and standings** Before querying fixtures or standings, you need the active `season_id` for a league. Using `include=currentSeason` on the league endpoint returns this in a single request.

#### When NOT to use this feature

* **Looking up fixtures directly:** Once you have a league ID, use the [Fixtures](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/livescores-and-fixtures/fixtures) endpoint with a date or date range filter. Leagues don't return fixtures directly unless you use the `upcoming` or `latest` include.
* **Checking which data features a league supports:** Use the [Data Features per League](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/data-features-per-league) reference instead.

### 2. How to retrieve data

#### Understanding the endpoints

**Base URL:**

```http
https://api.sportmonks.com/v3/football/leagues
```

**Available endpoints:**

| Endpoint                   | Path suffix               | Description                            |
| -------------------------- | ------------------------- | -------------------------------------- |
| GET All Leagues            | *(base URL)*              | All leagues in your subscription       |
| GET League by ID           | `/{league_id}`            | Single league by ID                    |
| GET Leagues by Country ID  | `/countries/{country_id}` | All leagues in a specific country      |
| GET League Search by Name  | `/search/{query}`         | Leagues matching a name search         |
| GET Leagues by Live        | `/live`                   | Leagues with active fixtures right now |
| GET League by Fixture Date | `/date/{YYYY-MM-DD}`      | Leagues with fixtures on a given date  |

**Available parameters:**

| Parameter   | Type   | Required | Description                   | Example                         |
| ----------- | ------ | -------- | ----------------------------- | ------------------------------- |
| `api_token` | string | Yes      | Your API authentication token | `YOUR_API_TOKEN`                |
| `include`   | string | No       | Related data to attach        | `currentSeason;upcoming;latest` |
| `select`    | string | No       | Specific fields to return     | `name,image_path`               |
| `filters`   | string | No       | Filter results                | `leagueCountries:1161`          |

#### Step-by-step implementation

**Step 1: GET All Leagues**

Returns every league your subscription has access to. This is the recommended first call when initialising your application, use the results to populate a league list and capture the IDs for subsequent queries.

```http
https://api.sportmonks.com/v3/football/leagues?api_token=YOUR_API_TOKEN
```

{% tabs %}
{% tab title="Javascript" %}

<pre class="language-javascript"><code class="lang-javascript">const apiToken = 'YOUR_API_TOKEN';

async function getAllLeagues(params = {}) {
  const query = new URLSearchParams({ api_token: apiToken, ...params });
  const response = await fetch(
    `https://api.sportmonks.com/v3/football/leagues?${query}`
  );
<strong>  if (!response.ok) throw new Error(`HTTP ${response.status}`);
</strong>  return response.json();
}

const leagues = await getAllLeagues();
</code></pre>

{% endtab %}

{% tab title="Python" %}

```python
import requests

def get_all_leagues(api_token, params=None):
    params = params or {}
    params['api_token'] = api_token
    r = requests.get(
        'https://api.sportmonks.com/v3/football/leagues',
        params=params,
        timeout=30
    )
    r.raise_for_status()
    return r.json()
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
function getAllLeagues($apiToken, $params = []) {
    $params['api_token'] = $apiToken;
    $url = 'https://api.sportmonks.com/v3/football/leagues?' . http_build_query($params);
    $response = file_get_contents($url);
    return json_decode($response, true);
}

$leagues = getAllLeagues('YOUR_API_TOKEN');
print_r($leagues);
?>
```

{% endtab %}
{% endtabs %}

**Step 2: GET League by ID**

Returns a single league. Use this when you already have the league ID and want to retrieve its details or current season.

```http
https://api.sportmonks.com/v3/football/leagues/8
?api_token=YOUR_API_TOKEN
```

**Step 3: GET Leagues by Country ID**

Returns all leagues belonging to a specific country.&#x20;

```http
https://api.sportmonks.com/v3/football/leagues/countries/
1161?api_token=YOUR_API_TOKEN
```

{% hint style="info" %}
**Tip:**  You can read `country_id` from entity responses or find the country id in mysportmonks dashboard
{% endhint %}

**Step 4: GET League Search by Name**

Returns leagues matching a text search. Useful when you know a league name but not its ID.

```http
https://api.sportmonks.com/v3/football/leagues/search/premier
?api_token=YOUR_API_TOKEN
```

{% hint style="info" %}
The more specific your query, the more relevant the results. Searching "premier" will return all leagues with "premier" in the name (e.g. Scottish Premiership, English Premier League, Premier Liga).
{% endhint %}

**Step 5: GET Leagues by Live**

Returns only the leagues that have at least one fixture currently in the livescore window. Useful for showing a dynamic list of active competitions.

```http
https://api.sportmonks.com/v3/football/leagues/live
?api_token=YOUR_API_TOKEN
```

{% hint style="info" %}
The response will be empty if no leagues in your subscription have active matches at the time of the request. Handle this case gracefully in your UI.
{% endhint %}

**Step 6: Adding includes**

The bare league response returns metadata only. The most important include is `currentSeason`, which gives you the active season ID needed for fixtures and standings queries.

```http
https://api.sportmonks.com/v3/football/leagues/8
?api_token=YOUR_API_TOKEN&include=currentSeason;upcoming;latest
```

Available includes for leagues:

* `currentSeason` : The active season, including its ID, name, start/end dates, and whether it's finished
* `seasons` : All historical seasons (use for building a season selector)
* `upcoming` : The next scheduled fixture in this league
* `latest` : The most recently played fixture in this league
* `country` : Country name and flag image

**Step 7: Selecting specific fields**

If you're building a league picker UI, you probably only need the name and logo. Use `select` to keep the response lean.

```http
https://api.sportmonks.com/v3/football/leagues
?api_token=YOUR_API_TOKEN&select=name,image_path
```

**Step 8: Complete example, league initialisation**

{% tabs %}
{% tab title="Javascript" %}

```javascript
class FootballAPI {
  constructor(apiToken) {
    this.token = apiToken;
    this.baseURL = 'https://api.sportmonks.com/v3/football';
  }

  async getLeagues(params = {}) {
    const query = new URLSearchParams({ api_token: this.token, ...params });
    const r = await fetch(`${this.baseURL}/leagues?${query}`);
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    return r.json();
  }

  async getLeague(leagueId, params = {}) {
    const query = new URLSearchParams({ api_token: this.token, ...params });
    const r = await fetch(`${this.baseURL}/leagues/${leagueId}?${query}`);
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    return r.json();
  }

  async getLiveLeagues(params = {}) {
    const query = new URLSearchParams({ api_token: this.token, ...params });
    const r = await fetch(`${this.baseURL}/leagues/live?${query}`);
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    return r.json();
  }
}

const api = new FootballAPI('YOUR_API_TOKEN');

// Populate league selector with name and logo only
const leagueList = await api.getLeagues({ select: 'name,image_path' });

// Get Scottish Premiership with current season info
const scottishPrem = await api.getLeague(501, { include: 'currentSeason' });
const currentSeasonId = scottishPrem.data.current_season?.id;

// Show only leagues with live matches
const liveLeagues = await api.getLiveLeagues({ include: 'currentSeason' });
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

class FootballAPI:
    def __init__(self, api_token):
        self.token = api_token
        self.base_url = 'https://api.sportmonks.com/v3/football'

    def get_leagues(self, params=None):
        params = params or {}
        params['api_token'] = self.token
        r = requests.get(f'{self.base_url}/leagues', params=params, timeout=30)
        r.raise_for_status()
        return r.json()

    def get_league(self, league_id, params=None):
        params = params or {}
        params['api_token'] = self.token
        r = requests.get(f'{self.base_url}/leagues/{league_id}', params=params, timeout=30)
        r.raise_for_status()
        return r.json()

api = FootballAPI('YOUR_API_TOKEN')
league_list = api.get_leagues({'select': 'name,image_path'})
scottish_prem = api.get_league(501, {'include': 'currentSeason'})
current_season_id = scottish_prem['data']['current_season']['id']
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
class FootballAPI {
    private $token;
    private $baseURL = 'https://api.sportmonks.com/v3/football';

    public function __construct($apiToken) {
        $this->token = $apiToken;
    }

    public function getLeagues($params = []) {
        $params['api_token'] = $this->token;
        $url = "{$this->baseURL}/leagues?" . http_build_query($params);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }

    public function getLeague($leagueId, $params = []) {
        $params['api_token'] = $this->token;
        $url = "{$this->baseURL}/leagues/{$leagueId}?" . http_build_query($params);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        $response = curl_exec($ch);
        curl_close($ch);

        return json_decode($response, true);
    }
}

$api = new FootballAPI('YOUR_API_TOKEN');
$leagueList = $api->getLeagues(['select' => 'name,image_path']);
$scottishPrem = $api->getLeague(501, ['include' => 'currentSeason']);
$currentSeasonId = $scottishPrem['data']['current_season']['id'];
print_r($leagueList);
?>
```

{% endtab %}
{% endtabs %}

### 3. Working with the data

#### Understanding the response structure

```json
{
  "data": {
    "id": 501,
    "sport_id": 1,
    "country_id": 1161,
    "name": "Premiership",
    "active": true,
    "short_code": "SCO P",
    "image_path": "https://cdn.sportmonks.com/images/soccer/leagues/501.png",
    "type": "league",
    "sub_type": "domestic",
    "last_played_at": "2023-02-25 15:00:00",
    "has_jerseys": false
  }
}
```

**Key fields:**

| Field            | Type    | Description                                                     |
| ---------------- | ------- | --------------------------------------------------------------- |
| `id`             | integer | Unique league identifier, use as `league_id` in other endpoints |
| `country_id`     | integer | The country this league belongs to                              |
| `name`           | string  | Full league name                                                |
| `short_code`     | string  | Abbreviated code (e.g. `"SCO P"`)                               |
| `image_path`     | string  | URL to the league logo                                          |
| `type`           | string  | `"league"` or `"cup"`                                           |
| `sub_type`       | string  | More specific classification (e.g. `"domestic"`, `"play-offs"`) |
| `active`         | boolean | Whether the league is currently active                          |
| `last_played_at` | string  | Datetime of the most recently played fixture                    |
| `has_jerseys`    | boolean | Whether jersey data is available for this league                |

#### Processing the data

**Build a league map for fast ID lookups:**

```javascript
const data = await api.getLeagues({ select: 'name,image_path' });

const leagueMap = new Map(
  data.data.map(league => [league.id, { name: league.name, logo: league.image_path }])
);

const leagueName = leagueMap.get(501)?.name; // "Premiership"
```

**Extract current season IDs for all leagues:**

```javascript
const data = await api.getLeagues({ include: 'currentSeason' });

const seasonIds = data.data
  .filter(league => league.current_season)
  .map(league => ({
    leagueId: league.id,
    leagueName: league.name,
    seasonId: league.current_season.id,
    seasonName: league.current_season.name
  }));
```

**Group leagues by country:**

```javascript
const data = await api.getLeagues({ include: 'country:name' });

const byCountry = {};
for (const league of data.data) {
  const country = league.country?.name || 'Unknown';
  if (!byCountry[country]) byCountry[country] = [];
  byCountry[country].push(league);
}
```

### 4. Common pitfalls

#### Pitfall 1: Expecting leagues outside your subscription

GET All Leagues only returns leagues included in your plan. If a specific league is missing, it is not in your subscription.

```javascript
// ❌ Assumption: a league will always be present
const epl = data.data.find(l => l.id === 8);
console.log(epl.name); // throws if EPL is not in your plan

// ✅ Safe approach
const epl = data.data.find(l => l.id === 8);
if (!epl) {
  console.warn('EPL not available in current subscription');
}
```

#### Pitfall 2: Fetching currentSeason on every request

`currentSeason` doesn't change frequently. Fetching it on every request wastes API calls.

```javascript
// ❌ Wrong: fetches season on every page load
async function getFixtures(leagueId) {
  const league = await api.getLeague(leagueId, { include: 'currentSeason' });
  const seasonId = league.data.current_season.id;
  return api.getStandings(seasonId);
}

// ✅ Correct: cache league and season data at startup
const leagueCache = new Map();

async function init() {
  const data = await api.getLeagues({ include: 'currentSeason' });
  for (const league of data.data) {
    leagueCache.set(league.id, {
      name: league.name,
      seasonId: league.current_season?.id
    });
  }
}
```

#### Pitfall 3: Empty response from GET Leagues by Live

No active matches means an empty array, not an error. Handle this in your UI.

```javascript
const live = await api.getLiveLeagues();

if (!live.data || live.data.length === 0) {
  renderEmptyState('No leagues with live matches right now.');
} else {
  renderLiveLeagues(live.data);
}
```

#### Pitfall 4: Confusing `type` with match state

The `type` and `sub_type` fields on the league object describe the competition format, not match state. `type: "league"` and `sub_type: "domestic"` describe the competition itself. Match states are separate, see [States](https://docs.sportmonks.com/v3/definitions/states).

### 5. Advanced usage

#### Advanced technique 1: One-shot app initialisation

Fetch all leagues with their current season in a single request at app startup and store the result. This gives you the foundation data needed for all other queries with just one API call.

```javascript
async function initApp() {
  const data = await api.getLeagues({
    include: 'currentSeason',
    select: 'name,image_path,active,type,sub_type'
  });

  const activeLeagues = data.data.filter(l => l.active && l.current_season);

  return {
    leagueList: activeLeagues.map(l => ({
      id: l.id,
      name: l.name,
      logo: l.image_path,
      seasonId: l.current_season.id,
      seasonName: l.current_season.name
    })),
    leagueMap: new Map(activeLeagues.map(l => [l.id, l]))
  };
}
```

#### Advanced technique 2: Historical season selector

Use `include=seasons` to retrieve all historical seasons for a league, enabling users to browse past tables and fixtures.

```javascript
async function getSeasonHistory(leagueId) {
  const data = await api.getLeague(leagueId, { include: 'seasons' });

  return data.data.seasons
    .sort((a, b) => new Date(b.starting_at) - new Date(a.starting_at))
    .map(s => ({ id: s.id, name: s.name, finished: s.finished }));
}
```

### 6. Common errors

#### 401 Unauthorised

**Cause:** Missing or invalid `api_token`. **Fix:** Confirm the token is correct and appended to every request. Retrieve it from [MySportmonks](https://my.sportmonks.com/).

#### 404 Not Found

**Cause:** The league ID does not exist or is not in your subscription. **Fix:** Use GET All Leagues to verify available IDs, or check the [ID Finder](https://my.sportmonks.com/resources/id-finder).

#### 429 Too Many Requests

**Cause:** Exceeded your plan's hourly API call limit. **Fix:** Cache league data at startup, it changes rarely. See the [Rate Limiting guide](https://docs.sportmonks.com/v3/api/rate-limit).

### See also

**Prerequisites**

* [Authentication](https://docs.sportmonks.com/v3/welcome/authentication) : Setting up API access
* [Includes](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes) : Attaching season and fixture data
* [Filter and Select Fields](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/filter-and-select-fields) : Narrowing and slimming responses

**Using leagues and seasons**

* [Seasons](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/leagues-and-seasons/seasons) : Season-level metadata and historical seasons
* [Fixtures](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/livescores-and-fixtures/fixtures) : Filter fixtures by league ID
* [Standings](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/standings) : League table for a given season
* [Season Schedule](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/season-schedule) : Rounds, stages, and groups for a season
* [Data Features per League](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/data-features-per-league) : What data is available for each league

**Related endpoints**

* [Leagues Endpoints](https://docs.sportmonks.com/v3/endpoints-and-entities/endpoints/leagues) : Complete API endpoint reference
* [Seasons Endpoints](https://docs.sportmonks.com/v3/endpoints-and-entities/endpoints/seasons) : Season data access
* [Countries Endpoint](https://docs.sportmonks.com/v3/endpoints-and-entities/endpoints/countries) : Country IDs for use with the country filter

### 8. FAQ

**Q: Why is a specific league not appearing in my GET All Leagues response?**

The league is not included in your current subscription plan. Check which leagues are available in your plan via [MySportmonks](https://my.sportmonks.com/), or consider upgrading.

**Q: How do I get the current season ID for a league?**

Add `include=currentSeason` to any league request. The `current_season.id` field in the response is the active season ID.

**Q: What's the difference between `type` and `sub_type` on a league?**

`type` indicates whether the competition is a `"league"` or `"cup"`. `sub_type` provides more detail: `"domestic"`, `"play-offs"`, `"international"`, etc.

**Q: How do I know if statistics or other data features are available for a league?**

See the [Data Features per League](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/data-features-per-league) reference, which lists what data types are covered per competition.

**Q: Can I get all leagues in a continent rather than a country?**

There is no continent filter. Use the country-level endpoint and query each relevant country separately, or filter client-side from the GET All Leagues response.

**Q: How often does league data change?**

League metadata (name, logo, type) changes rarely. `last_played_at` updates after each match. Cache league data at startup and refresh on a daily basis at most.

#### Best practices summary

✅ DO:

* Fetch all leagues with `include=currentSeason` at app startup and cache the result
* Use `select=name,image_path` to keep league list responses lean
* Use GET Leagues by Country ID or GET League Search by Name when you already know the scope
* Handle empty responses from GET Leagues by Live gracefully

❌ DON'T:

* Re-fetch league data on every page load, it rarely changes
* Assume a league will be in the response without checking
* Use the leagues endpoint to retrieve fixture data, use the Fixtures endpoint with a `filters=fixtureLeagues:{id}` parameter


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/leagues-and-seasons/leagues.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
