---
title: "Domestic-league expected-goals leaderboard (season aggregates)"
method: GET
path: "/v1/leagues/{id}/xg-leaders"
tags: ["sports"]
---

# Domestic-league expected-goals leaderboard (season aggregates)

`GET /v1/leagues/{id}/xg-leaders`

## Request

- Base URL: `https://api.bigballsdata.com`
- URL: `https://api.bigballsdata.com/v1/leagues/{id}/xg-leaders`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

Per-league season xG leaderboard for the big-five European leagues,
2014 through the current season. Ranks players by expected goals and
exposes the surrounding shot-quality picture: xG, xA, npxG, xGChain,
xGBuildup, plus goals, assists, shots, key passes, matches and minutes.
`goals_above_xg` (goals minus xG) is derived for finishing over- and
under-performance.

**Solo plan or higher**: every field this endpoint ranks on is a model
estimate rather than a record of what happened, so it sits with the rest
of the model layer. Free receives a 403 naming the tier and linking the
docs and pricing pages. The factual view of the same leagues, goals and
assists, stays free on `GET /v1/leagues/{id}/top-scorers`.

LEAGUE-LEVEL ONLY. Rows are keyed by player NAME, not by a BigBalls
`player_id`; the xG-to-players entity bridge is not built yet,
so a per-player or per-match xG surface would serve a mostly-empty
join. Those endpoints are not offered until that bridge lands; see
docs/scoping/soccer-xg-bridge.md. Season rows we cannot attribute to a
league are excluded, so this leaderboard only ever reflects players in
the league you asked for.

`team` is the source team title verbatim and may be a comma-separated
list for a player who transferred mid-season. Refreshed daily;
when `season` is omitted, this endpoint and the sibling top-scorers
endpoint use the newest season present in both datasets. 5-minute
Redis cache keyed by league+season+stat+min_minutes+limit.

## Path parameters

- `id` 'epl' | 'laliga' | 'serie-a' | 'bundesliga' | 'ligue-1', required

## Query parameters

- `stat` 'xg' | 'xa' | 'npxg' | 'goals' | 'assists' | 'shots' | 'key_passes'
- `season` integer
- `min_minutes` integer
- `limit` integer

## Response `200`

ok

- object
  - `data` object
    - `league` object, required
      - `id` string: The league code you requested.
      - `name` string, nullable
    - `season` integer, required
    - `stat` string, required
    - `min_minutes` integer, required
    - `leaders` object[], required
      - `rank` integer
      - `player_name` string
      - `team` string, nullable: Source team title; a comma-list on a mid-season transfer.
      - `position` string, nullable
      - `matches` integer, nullable
      - `minutes` integer, nullable
      - `goals` integer, nullable
      - `assists` integer, nullable
      - `shots` integer, nullable
      - `key_passes` integer, nullable
      - `xg` number, nullable
      - `xa` number, nullable
      - `npxg` number, nullable
      - `xg_chain` number, nullable
      - `xg_buildup` number, nullable
      - `goals_above_xg` number, nullable
  - `updated_at` string, date-time, nullable
  - `meta` object
    - `cached` boolean
    - `cache_age_ms` integer

## Other responses

- `400`: Invalid query parameter. Carries a suggested_fix naming the legal values.
- `404`: League has no xG coverage. The error names the leagues that do.

---

[API](https://skmtc.dev/bigballsdata/apis/big-ball-sports-api.md) · [All operations](https://skmtc.dev/bigballsdata/apis/big-ball-sports-api/llms.txt) · [OpenAPI document](https://skmtc.dev/bigballsdata/apis/big-ball-sports-api/revisions/31fb54ac414e?raw)
