> ## Documentation Index
> Fetch the complete documentation index at: https://www.thestatsapi.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> For the complete API reference (every endpoint, query parameter and response field), fetch https://api.thestatsapi.com/llms.txt. Only use endpoints, parameters and fields listed there.
> Base URL: https://api.thestatsapi.com/api. Auth header: Authorization: Bearer YOUR_API_KEY. Keep the key in server-side code only.

# List coverage by competition

> Returns one row per competition: how many seasons are loaded, which data types it has (fixtures, team stats, xG, odds, lineups, player stats, standings), the latest season's status and the number of finished matches. Use it to check what's available before you build. Add `data_type` to list only competitions that have that data. Counts only include finished matches, and responses are cached for several hours.

**Example:** `GET /coverage/leagues?data_type=xg&search=Premier`


How to check coverage before you build: [Coverage](/docs/concepts/coverage).


## OpenAPI

````yaml GET /coverage/leagues
openapi: 3.0.0
info:
  title: TheStatsAPI
  description: >
    Football data REST API: competitions, seasons, teams, players and matches,
    with scores, team and player stats, xG, lineups, event timelines and betting
    odds where available.


    **Base URL:** `https://api.thestatsapi.com/api`. **Auth:** send
    `Authorization: Bearer YOUR_API_KEY` on every request. Get a key at
    https://www.thestatsapi.com/api-keys. IDs are prefixed strings: `comp_`
    competition, `sn_` season, `tm_` team, `mt_` match, `pl_` player.


    **Building with AI?** Give your coding tool (Claude Code, Codex, Cursor,
    Lovable) https://api.thestatsapi.com/llms.txt. It is this whole reference,
    every endpoint, parameter and response shape, as one Markdown file. The
    OpenAPI spec is at https://api.thestatsapi.com/openapi.json and the guides
    are at https://www.thestatsapi.com/docs.


    **Coverage:** history depth varies by competition. Check `GET
    /coverage/leagues` to see which seasons and data types each competition has.
    Data is pull-only: poll the live endpoints during a match (there are no
    webhooks or streams).


    **Rate limits and quota:** every authenticated response, success or error,
    carries two separate budgets.


    - Per minute: `X-RateLimit-Limit`, `X-RateLimit-Remaining`,
    `X-RateLimit-Reset` (unix seconds at the next minute boundary).

    - Per monthly billing cycle: `X-Monthly-Quota-Limit`,
    `X-Monthly-Quota-Remaining`, `X-Monthly-Quota-Reset` (unix seconds when the
    cycle rolls over). Limit and Remaining are `-1` on plans with no monthly
    cap.


    Each `Remaining` value already counts the request being served, so `0` means
    your next request is rejected. Trial subscriptions are metered at 10% of the
    plan's limits. Going over either budget returns `429` with a `Retry-After`
    header: code `RATE_LIMITED` for the per-minute window,
    `USAGE_LIMIT_EXCEEDED` for the monthly quota. Plans and limits:
    https://www.thestatsapi.com/#pricing.


    **Errors:** every error uses the same envelope, for example `{"error":
    {"code": "NOT_FOUND", "message": "Match not found", "status_code": 404}}`.
    Branch on `code`:


    | Status | Code | Meaning |

    |--------|------|---------|

    | 400 | `BAD_REQUEST` | A parameter is missing or invalid, e.g. `season_id
    is required`. |

    | 400 | `UNKNOWN_PARAMETER` | The endpoint doesn't accept a query parameter
    you sent, e.g. `date` instead of `date_from`. The message suggests the
    closest name and lists the accepted ones. |

    | 400 | `SEASON_COMPETITION_MISMATCH`, `PAGE_OUT_OF_RANGE` | `season_id`
    belongs to a different `competition_id`, or `page` is past the last page. |

    | 401 | `UNAUTHORIZED` | The API key is missing or invalid. |

    | 403 | `FORBIDDEN`, `KEY_REVOKED`, `ADDON_REQUIRED` | The key or account is
    inactive or expired, there is no active plan, or the endpoint needs an
    add-on. |

    | 404 | `NOT_FOUND`, `STATS_NOT_AVAILABLE_AT_SOURCE` | The ID or route
    doesn't exist, or detailed stats were never collected for the match. |

    | 409 | `CONFLICT`, `MATCH_IS_LIVE` | A live-only endpoint was called for a
    match that isn't live, or a post-match endpoint while it is. |

    | 429 | `RATE_LIMITED`, `USAGE_LIMIT_EXCEEDED` | Per-minute limit or monthly
    quota reached. Wait `Retry-After` seconds. |
  version: 1.0.0
servers:
  - url: https://api.thestatsapi.com/api
    description: Production server
security:
  - BearerAuth: []
tags:
  - name: Competitions
    description: >-
      Leagues, cups and tournaments, with their seasons, groups and standings.
      Start here to find a `competition_id` and `season_id`.
  - name: Teams
    description: Teams, squads, season stats, standings history, injuries and suspensions.
  - name: Matches
    description: >-
      Fixtures and results, plus per-match stats, live stats, lineups,
      timelines, shotmaps, heatmaps and referees.
  - name: Players
    description: >-
      Player profiles, season stats, injuries and suspensions, and season
      heatmaps.
  - name: Odds
    description: >-
      Pre-match, in-play and player-prop odds for a match from Bet365, Paddy
      Power, BetMGM UK, Pinnacle and Betfair Exchange.
  - name: Coverage
    description: >-
      Which competitions and seasons have which data types, and how complete
      they are. Check here before you build.
  - name: Health
    description: Check that the API is up.
externalDocs:
  description: Guides and quickstart
  url: https://www.thestatsapi.com/docs
paths:
  /coverage/leagues:
    get:
      tags:
        - Coverage
      summary: List coverage by competition
      description: >
        Returns one row per competition: how many seasons are loaded, which data
        types it has (fixtures, team stats, xG, odds, lineups, player stats,
        standings), the latest season's status and the number of finished
        matches. Use it to check what's available before you build. Add
        `data_type` to list only competitions that have that data. Counts only
        include finished matches, and responses are cached for several hours.


        **Example:** `GET /coverage/leagues?data_type=xg&search=Premier`
      operationId: listCoverageLeagues
      parameters:
        - $ref: '#/components/parameters/Page'
        - name: per_page
          in: query
          required: false
          description: Results per page (default 100, max 200)
          schema:
            type: integer
            default: 100
            maximum: 200
          example: 50
        - name: data_type
          in: query
          required: false
          description: Only competitions that have this data type
          schema:
            type: string
            enum:
              - fixtures
              - team_stats
              - xg
              - odds
              - opening_odds
              - closing_odds
              - lineups
              - player_stats
              - standings
          example: xg
        - name: search
          in: query
          required: false
          description: Part of the competition name, case-insensitive
          schema:
            type: string
          example: Premier
      responses:
        '200':
          description: A page of competitions with coverage.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/CoverageLeague'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
components:
  parameters:
    Page:
      name: page
      in: query
      description: >-
        Page number, starting at 1. `meta.total_pages` tells you how many there
        are
      schema:
        type: integer
        minimum: 1
        default: 1
      example: 1
  schemas:
    CoverageLeague:
      type: object
      properties:
        id:
          type: string
          example: comp_3039
        name:
          type: string
          example: Premier League
        country:
          type: string
          nullable: true
          example: England
        country_code:
          type: string
          nullable: true
          example: GB
        seasons:
          type: object
          description: >-
            Seasons with matches loaded. `first` and `last` are not always the
            oldest and newest season; for the full list use `GET
            /coverage/leagues/{competition_id}`.
          properties:
            count:
              type: integer
              example: 13
            first:
              allOf:
                - $ref: '#/components/schemas/CoverageSeasonRef'
              example:
                id: sn_612289
                year: 14/15
            last:
              $ref: '#/components/schemas/CoverageSeasonRef'
        data_types:
          allOf:
            - $ref: '#/components/schemas/CoverageDataTypes'
          example:
            fixtures:
              available: true
            team_stats:
              available: true
            xg:
              available: true
            odds:
              available: true
            opening_odds:
              available: true
            closing_odds:
              available: true
            lineups:
              available: true
            player_stats:
              available: true
            standings:
              available: true
        latest_season:
          type: object
          nullable: true
          properties:
            id:
              type: string
              example: sn_8406098
            year:
              type: string
              nullable: true
              example: 26/27
            status:
              $ref: '#/components/schemas/CoverageSeasonStatus'
            finished_events:
              type: integer
              example: 50
            total_events:
              type: integer
              example: 100
        total_finished_events:
          type: integer
          example: 4610
    PaginationMeta:
      type: object
      properties:
        page:
          type: integer
          example: 1
        per_page:
          type: integer
          example: 20
        total:
          type: integer
          example: 100
        total_pages:
          type: integer
          example: 5
    CoverageSeasonRef:
      type: object
      nullable: true
      properties:
        id:
          type: string
          example: sn_8406098
        year:
          type: string
          nullable: true
          example: 26/27
    CoverageDataTypes:
      type: object
      description: >-
        Keyed by data type name. New keys may be added, so ignore keys you don't
        recognise.
      properties:
        fixtures:
          $ref: '#/components/schemas/CoverageDataTypeEntry'
        team_stats:
          $ref: '#/components/schemas/CoverageDataTypeEntry'
        xg:
          $ref: '#/components/schemas/CoverageDataTypeEntry'
        odds:
          allOf:
            - $ref: '#/components/schemas/CoverageDataTypeEntry'
          description: Alias of closing_odds, kept for existing clients.
        opening_odds:
          allOf:
            - $ref: '#/components/schemas/CoverageDataTypeEntry'
          description: >-
            Opening prices (first price captured per selection) are stored.
            These fill the `opening` field on
            `/football/matches/{match_id}/odds`.
        closing_odds:
          allOf:
            - $ref: '#/components/schemas/CoverageDataTypeEntry'
          description: >-
            Closing prices (last pre-match price before kickoff) are stored.
            These fill the `last_seen` field on
            `/football/matches/{match_id}/odds`.
        lineups:
          $ref: '#/components/schemas/CoverageDataTypeEntry'
        player_stats:
          $ref: '#/components/schemas/CoverageDataTypeEntry'
        standings:
          $ref: '#/components/schemas/CoverageDataTypeEntry'
      additionalProperties:
        $ref: '#/components/schemas/CoverageDataTypeEntry'
    CoverageSeasonStatus:
      type: string
      description: >-
        `complete`: every loaded match has been played. `in_progress`: some
        loaded matches are still to come. `not_loaded`: no matches are loaded
        for the season. Based on the matches loaded so far. More values may be
        added later.
      enum:
        - complete
        - in_progress
        - not_loaded
    Error:
      type: object
      description: |
        Every error uses this envelope. `code` is a stable UPPERCASE string
        to branch on: `BAD_REQUEST`, `UNKNOWN_PARAMETER`,
        `SEASON_COMPETITION_MISMATCH`, `PAGE_OUT_OF_RANGE` (400);
        `UNAUTHORIZED` (401); `FORBIDDEN`, `KEY_REVOKED`, `ADDON_REQUIRED`
        (403); `NOT_FOUND`, `STATS_NOT_AVAILABLE_AT_SOURCE` (404);
        `METHOD_NOT_ALLOWED` (405, every endpoint is `GET`); `CONFLICT`,
        `MATCH_IS_LIVE` (409); `RATE_LIMITED`, `USAGE_LIMIT_EXCEEDED` (429);
        `INTERNAL_SERVER_ERROR` (500). `message` explains the problem in
        plain English.
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - status_code
          properties:
            code:
              type: string
              description: UPPERCASE error code. See the list above.
              example: BAD_REQUEST
            message:
              type: string
              description: What went wrong, in plain English.
              example: season_id is required
            status_code:
              type: integer
              description: The HTTP status code, repeated in the body.
              example: 400
    CoverageDataTypeEntry:
      type: object
      required:
        - available
      properties:
        available:
          type: boolean
        covered_events:
          type: integer
          description: >-
            Finished matches that have this data type. Only on `GET
            /coverage/leagues/{competition_id}`
          example: 380
        coverage_pct:
          type: number
          description: >-
            Share of finished matches that have this data type, as a percentage
            with one decimal. Only on `GET /coverage/leagues/{competition_id}`
          example: 100
  responses:
    BadRequest:
      description: >
        The request is invalid. `UNKNOWN_PARAMETER` means you sent a query
        parameter this endpoint doesn't accept; the message suggests the closest
        name and lists the accepted ones. Otherwise `code` is usually
        `BAD_REQUEST` and `message` says which parameter is wrong.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            unknown_parameter:
              summary: Unknown query parameter (from /football/matches)
              value:
                error:
                  code: UNKNOWN_PARAMETER
                  message: >-
                    Unknown query parameter 'date' (did you mean 'date_from' or
                    'date_to'?). Supported parameters: page, per_page, limit,
                    competition_id, season_id, team_id, date_from, date_to,
                    utc_offset, matchday, status, stage, group, sort.
                  status_code: 400
            missing_parameter:
              summary: Missing required parameter
              value:
                error:
                  code: BAD_REQUEST
                  message: season_id is required
                  status_code: 400
            season_mismatch:
              summary: Season from a different competition
              value:
                error:
                  code: SEASON_COMPETITION_MISMATCH
                  message: season_id does not belong to competition_id
                  status_code: 400
    Unauthorized:
      description: >
        The API key is missing or invalid. Send it as `Authorization: Bearer
        YOUR_API_KEY`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missing_header:
              summary: No Authorization header
              value:
                error:
                  code: UNAUTHORIZED
                  message: Missing authorization header
                  status_code: 401
            invalid_key:
              summary: Unknown API key
              value:
                error:
                  code: UNAUTHORIZED
                  message: Invalid API key
                  status_code: 401
    TooManyRequests:
      description: >
        Too many requests: the per-minute rate limit (`RATE_LIMITED`) or the
        monthly quota (`USAGE_LIMIT_EXCEEDED`) is used up. Wait `Retry-After`
        seconds before retrying. The quota headers are sent here as on any other
        authenticated response.
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
        X-Monthly-Quota-Limit:
          $ref: '#/components/headers/XMonthlyQuotaLimit'
        X-Monthly-Quota-Remaining:
          $ref: '#/components/headers/XMonthlyQuotaRemaining'
        X-Monthly-Quota-Reset:
          $ref: '#/components/headers/XMonthlyQuotaReset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            rate_limited:
              summary: Per-minute rate limit reached
              value:
                error:
                  code: RATE_LIMITED
                  message: Rate limit exceeded. Please slow down your requests.
                  status_code: 429
            usage_limit_exceeded:
              summary: Monthly quota used up
              value:
                error:
                  code: USAGE_LIMIT_EXCEEDED
                  message: Monthly usage limit exceeded. Please upgrade your plan.
                  status_code: 429
  headers:
    RetryAfter:
      description: >
        Seconds to wait before retrying. Sent only on `429` responses, and
        always the real time until the budget that rejected you clears, so it
        agrees with the matching reset header: waiting exactly this long lands
        on that timestamp.


        On `RATE_LIMITED` it is the time left in the current one-minute window
        (`X-RateLimit-Reset`) and can be as little as 1 second near a boundary.
        On `USAGE_LIMIT_EXCEEDED` it is the time until the billing cycle rolls
        over (`X-Monthly-Quota-Reset`) and is therefore large — days, not
        seconds. Retrying sooner than that returns `429` again for the rest of
        the cycle; upgrade the plan instead.
      schema:
        type: integer
    XRateLimitLimit:
      description: >-
        Maximum requests allowed in the current one-minute window for this API
        key and product.
      schema:
        type: integer
    XRateLimitRemaining:
      description: >
        Requests remaining in the current one-minute window, counting the
        request being served.
      schema:
        type: integer
    XRateLimitReset:
      description: Unix timestamp, in seconds, when the current rate-limit window resets.
      schema:
        type: integer
    XMonthlyQuotaLimit:
      description: >
        Requests allowed in the current monthly billing cycle for this user and
        product. `-1` on plans with no monthly cap.
      schema:
        type: integer
    XMonthlyQuotaRemaining:
      description: >
        Requests remaining in the current monthly billing cycle, counting the
        request being served. `-1` on plans with no monthly cap.
      schema:
        type: integer
    XMonthlyQuotaReset:
      description: Unix timestamp, in seconds, when the monthly billing cycle rolls over.
      schema:
        type: integer
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your API key, sent as `Authorization: Bearer YOUR_API_KEY`. Get one at
        https://www.thestatsapi.com/api-keys

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.