API reference

Reference for the 4league public /v1 API. English only. Requests must be signed: see HMAC authentication. Everything on this page is generated from the same machine-readable description of the API.

Conventions

Base URL and methods

Base URL: https://api.4league.app/v1. Do not use 4league.app/api; it is not this API. Requests are signed, see HMAC authentication.

Only GET, HEAD are served. Any other method answers 405 methodNotAllowed with an Allow: GET, HEAD header, before authentication. Request bodies are rejected with 400 badRequest. OPTIONS is normally answered (204) by CORS before reaching the API.

Organization-scoped keys only. A key sees its own organization and, when created with descendants, everything below it. Anything outside the scope, hidden, or nonexistent answers the identical 404 notFound.

Pagination

List endpoints return this envelope. Defaults: page 1, limit 25 (max 100). page * limit must be <= 10000 (10000). 400 badRequest with details {field, limit}. Repeated keys and arrays are rejected.

FieldType
dataarray
pageinteger
limitinteger
totalinteger
hasMoreboolean (page * limit < total)

Some paginated responses add top-level competition and/or meta (kind, truncated, competitionsIncluded). Window cap: Enforced (400 badRequest, details.field page) on the organization list routes and on /tournaments/{id}/teams and /tournaments/{id}/players (all via helpers/apiData/orgListCache.js page()). Not enforced on the other paginated routes, which slice an in-memory list: any page is accepted and an out-of-range page returns an empty data array.

Query parameters and sorting

Unknown, repeated (array) or empty query keys are 400 badRequest with details.field. Values are case-sensitive. The error carries details.field with the offending key.

Sorting: sort accepts id, name; prefix with - for descending (id, name, -id, -name). Ascending, or descending with a - prefix. Always tie-broken on id.

Time filters: from and to

  • Format: ISO 8601, inclusive on both ends.
  • A date-only value (YYYY-MM-DD) covers the whole UTC day: from = 00:00:00.000Z, to = 23:59:59.999Z.
  • Bounds are compared in UTC. A value with an offset is converted to UTC; a value without an offset is read as UTC.
  • The competition timezone is used only to place legacy matches that have no stored timestamp.
  • Send full timestamps with an explicit offset (for example 2026-01-05T10:00:00+02:00).
  • 400 badRequest, details.field = from | to. from after to is 400 with details.field = from.

Errors

Every error uses this body; reason, details and retryAfter are optional:

{
  "error": {
    "code": "string",
    "message": "string",
    "reason": "optional string",
    "details": "optional object",
    "retryAfter": "optional integer seconds"
  }
}
StatusCodeWhen
401unauthorizedAuthentication failed: malformed or missing X-4League-* headers, unknown or revoked key, timestamp outside the window, bad signature or replayed nonce. All variants have the same status and message.
malformedHeader may change
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid credentials",
    "reason": "malformedHeader"
  }
}
The reason field is returned today only for malformed or missing headers. The owner is still deciding whether all 401 bodies should be identical; do not rely on reason.
otherFailures
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid credentials"
  }
}
Unknown or revoked key, stale timestamp, bad signature, replayed nonce: no reason field.
403forbiddenThe request IP is not on the key IP allowlist, or includeDescendants=true was sent with a key created without descendants.
403scopeMissingThe key lacks the scope the route requires (checked before the resource is looked up).
403proRequiredThe owning organization is inactive or has no PRO plan.
404notFoundUnknown route, or a resource that does not exist, is outside the key scope, is hidden/private, has the wrong type for the alias, or has a malformed id. All look identical.
405methodNotAllowedAny method other than GET and HEAD.
400badRequestInvalid query parameter, unknown query key, invalid pagination, or a request body.
details: {"field":"name of the offending parameter","limit":"present on page/limit errors"}
422scopeTooLargeincludeDescendants=true on an organization list whose scope exceeds the maximum, or the players list with more than 50 organizations in scope and no narrowing filter.
details: {"max":5000}
scope above MAX_SCOPE_ORGS: {"max":5000}
players list, more than 50 organizations and no narrowing filter: {"max":50,"requiresOneOf":["clubId","associationId","competitionId","teamId"]}
429rateLimitedMore than 60 requests per minute for the key (per worker), or the failed-authentication limit for the caller IP was reached.
retryAfter: seconds, also the Retry-After header
429quotaExceededThe monthly quota of the resource is used up.
retryAfter: seconds until the next month, also the Retry-After header
500internalErrorUnexpected server error. The message never contains internals.
503integrationsUnavailableThe credential store is unavailable.
503serviceUnavailableA dependency needed to authenticate or count the request is temporarily unavailable.

scopeTooLarge caps: scope above MAX_SCOPE_ORGS ({"max":5000}); players list, more than 50 organizations and no narrowing filter ({"max":50,"requiresOneOf":["clubId","associationId","competitionId","teamId"]}). Organization tree: at most 500 nodes, depth up to 3.

Scopes

ScopeEndpoints
organizations:read/{alias}/{id}, /{alias}/{id}/tree, /{alias}/{id}/associations, /{alias}/{id}/clubs
competitions:read/{alias}/{id}/competitions, /tournaments/{id}, /tournaments/{id}/groups, /tournaments/{id}/statistics
matches:read/tournaments/{id}/matches, /matches/{id}, /matches/{id}/lineups, /matches/{id}/events, /teams/{id}/matches, /players/{id}/matches
standings:read/tournaments/{id}/standings
teams:read/{alias}/{id}/teams, /tournaments/{id}/teams, /teams/{id}, /teams/{id}/statistics
players:read/{alias}/{id}/players, /tournaments/{id}/players, /tournaments/{id}/statistics, /tournaments/{id}/top-scorers, /tournaments/{id}/cards, /teams/{id}/players, /players/{id}, /players/{id}/statistics
matchStatistics:read/matches/{id}/statistics

Rate limits

Approximately 60 requests per minute per key, per server process. The limiter is per key and per server worker (in memory), so the effective limit is approximate: up to 60 x number of workers per minute. The standard RateLimit-* headers are not sent. Semantics read from middleware/apiAuth.js (express-rate-limit legacy headers); scripts/v1-signed-get.js prints the headers as received and defines no semantics of its own.

Monthly quota

10000 requests per resource per month (UTC calendar month). Headers: none: remaining quota is not exposed in headers. Counted per resource (organization), not per key. 429 quotaExceeded with Retry-After until the next month starts. Requests that fail authentication, the scope check or the rate limit do not consume quota; requests that pass all three do, including those that end in 404 or 400. A credential may carry its own monthlyQuota; 10000 is the default.

Caching and freshness

Data is cached for about 2 minutes at most: public data results for 30-60 seconds and the organization scope tree for 60 seconds, both per server worker, so two requests may see different states. Live matches use the shortest TTL.

Response headers

HeaderValueWhen
X-4League-Api-Version1Every response, including 401, 404, 405, 429, 500 and 503.
X-Request-Idrandom UUID per requestEvery response that passes the router.
X-RateLimit-Limit–Authenticated routes after the scope check (the per-key limiter). Requests per window: 60.
X-RateLimit-Remaining–Same as X-RateLimit-Limit. Requests left in the current 60-second window.
X-RateLimit-Reset–Same as X-RateLimit-Limit. Unix time in seconds when the window resets.
Retry-After–429 responses (rateLimited, quotaExceeded). Seconds, also in error.retryAfter.
AllowGET, HEAD405 responses.
Cache-Controlno-storeSuccessful data responses.

Quote X-Request-Id when you contact support about a request.

Organization aliases

  • organizations: any organization type (federation, association, club)
  • federations: federations only (type 2)
  • associations: associations only (type 3)
  • clubs: clubs only (type 4)

Wrong type: 404 notFound, identical to an unknown id.

Connectivity check

GET HEAD /ping

https://api.4league.app/v1/ping no scope

Authenticated echo, no scope required. Never cached (Cache-Control: no-store).

Parameters

No parameters.

Example request

curl -sS "https://api.4league.app/v1/ping" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/ping), HTTP 200.

{
  "data": {
    "apiVersion": 1,
    "serverTime": "2026-10-13T07:22:37.759Z",
    "keyId": "key1",
    "resourceType": "organization",
    "resourceId": "64b000000000000000000001",
    "scopes": [
      "competitions:read",
      "matches:read",
      "standings:read",
      "teams:read",
      "players:read",
      "matchStatistics:read",
      "organizations:read"
    ]
  }
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

Organizations

GET HEAD /{alias}/{id}

https://api.4league.app/v1/{alias}/{id} organizations:read

Aliases for {alias}: organizations, federations, associations, clubs.

One organization. includeDescendants=true (or a key created with descendants) is needed to address organizations below the key root.

Parameters

NameInTypeAllowedDefaultDescription
aliaspathstringone of organizations | federations | associations | clubs–Organization type alias, see Organization aliases.
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
includeDescendantsquerybooleanone of true | falsefalseInclude organizations below the addressed one (only within the key scope; keys created with descendants=false get 403 forbidden).

Example request

curl -sS "https://api.4league.app/v1/organizations/{orgId}" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/organizations/{orgId}), HTTP 200.

{
  "data": {
    "id": "64b000000000000000000001",
    "type": "federation",
    "name": "Fed",
    "logo": "https://cdn.test/f.png",
    "parentId": null,
    "description": "root",
    "season": null
  }
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /{alias}/{id}/tree

https://api.4league.app/v1/{alias}/{id}/tree organizations:read

Aliases for {alias}: organizations, federations, associations, clubs.

Hierarchy below the organization (follows the primary parent only). Capped at 500 nodes: a larger tree is cut and the response carries top-level truncated:true.

Extra top-level response fields: truncated.

Parameters

NameInTypeAllowedDefaultDescription
aliaspathstringone of organizations | federations | associations | clubs–Organization type alias, see Organization aliases.
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
depthqueryintegermin 1, max 32Levels below the addressed organization.
includeDescendantsquerybooleanone of true | falsefalseInclude organizations below the addressed one (only within the key scope; keys created with descendants=false get 403 forbidden).

Example request

curl -sS "https://api.4league.app/v1/organizations/{orgId}/tree?depth=2" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/organizations/{orgId}/tree?depth=2), HTTP 200.

{
  "data": {
    "id": "64b000000000000000000001",
    "type": "federation",
    "name": "Fed",
    "logo": "https://cdn.test/f.png",
    "parentId": null,
    "description": "root",
    "season": null,
    "children": [
      {
        "id": "6acddc3d41a6e2f5682625e3",
        "type": "association",
        "name": "org-6acddc3d41a6e2f5682625e3",
        "logo": "https://cdn.test/l.png",
        "parentId": "64b000000000000000000001",
        "description": "d",
        "season": null,
        "children": [
          {
            "id": "6acddc3d41a6e2f5682625e4",
            "type": "club",
            "name": "org-6acddc3d41a6e2f5682625e4",
            "logo": "https://cdn.test/l.png",
            "parentId": "6acddc3d41a6e2f5682625e3",
            "description": "d",
            "season": null,
            "children": []
          },
          {
            "id": "6acddc3d41a6e2f5682625e5",
            "type": "club",
            "name": "org-6acddc3d41a6e2f5682625e5",
            "logo": "https://cdn.test/l.png",
            "parentId": "6acddc3d41a6e2f5682625e3",
            "description": "d",
            "season": null,
            "children": []
          }
        ]
      }
    ]
  }
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /{alias}/{id}/associations

https://api.4league.app/v1/{alias}/{id}/associations organizations:read

Aliases for {alias}: organizations, federations, associations, clubs.

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
aliaspathstringone of organizations | federations | associations | clubs–Organization type alias, see Organization aliases.
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
statusquerystringone of active | inactive–
includeDescendantsquerybooleanone of true | falsefalseInclude organizations below the addressed one (only within the key scope; keys created with descendants=false get 403 forbidden).
sortquerystringone of id | name | -id | -nameidAscending, or descending with a - prefix. Always tie-broken on id.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/organizations/{orgId}/associations?limit=2" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/organizations/{orgId}/associations?limit=2), HTTP 200.

{
  "data": [
    {
      "id": "6acddc3d41a6e2f5682625e3",
      "type": "association",
      "name": "org-6acddc3d41a6e2f5682625e3",
      "logo": "https://cdn.test/l.png",
      "parentId": "64b000000000000000000001",
      "description": "d",
      "season": null
    }
  ],
  "page": 1,
  "limit": 2,
  "total": 1,
  "hasMore": false
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /{alias}/{id}/clubs

https://api.4league.app/v1/{alias}/{id}/clubs organizations:read

Aliases for {alias}: organizations, federations, associations, clubs.

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
aliaspathstringone of organizations | federations | associations | clubs–Organization type alias, see Organization aliases.
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
associationIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
statusquerystringone of active | inactive–
includeDescendantsquerybooleanone of true | falsefalseInclude organizations below the addressed one (only within the key scope; keys created with descendants=false get 403 forbidden).
sortquerystringone of id | name | -id | -nameidAscending, or descending with a - prefix. Always tie-broken on id.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/federations/{orgId}/clubs?includeDescendants=true&limit=2" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/federations/{orgId}/clubs?includeDescendants=true&limit=2), HTTP 200.

{
  "data": [
    {
      "id": "6acddc3d41a6e2f5682625e4",
      "type": "club",
      "name": "org-6acddc3d41a6e2f5682625e4",
      "logo": "https://cdn.test/l.png",
      "parentId": "6acddc3d41a6e2f5682625e3",
      "description": "d",
      "season": null
    },
    {
      "id": "6acddc3d41a6e2f5682625e5",
      "type": "club",
      "name": "org-6acddc3d41a6e2f5682625e5",
      "logo": "https://cdn.test/l.png",
      "parentId": "6acddc3d41a6e2f5682625e3",
      "description": "d",
      "season": null
    }
  ],
  "page": 1,
  "limit": 2,
  "total": 2,
  "hasMore": false
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /{alias}/{id}/competitions

https://api.4league.app/v1/{alias}/{id}/competitions competitions:read

Aliases for {alias}: organizations, federations, associations, clubs.

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
aliaspathstringone of organizations | federations | associations | clubs–Organization type alias, see Organization aliases.
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
associationIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
clubIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
teamIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
genderquerystringone of men | women–
statusquerystringone of active | completed–active = not completed and not expired; completed = completed.
includeDescendantsquerybooleanone of true | falsefalseInclude organizations below the addressed one (only within the key scope; keys created with descendants=false get 403 forbidden).
sortquerystringone of id | name | -id | -nameidAscending, or descending with a - prefix. Always tie-broken on id.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/{alias}/{id}/competitions" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /{alias}/{id}/teams

https://api.4league.app/v1/{alias}/{id}/teams teams:read

Aliases for {alias}: organizations, federations, associations, clubs.

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
aliaspathstringone of organizations | federations | associations | clubs–Organization type alias, see Organization aliases.
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
associationIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
clubIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
competitionIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
statusquerystringone of active | inactive–
includeDescendantsquerybooleanone of true | falsefalseInclude organizations below the addressed one (only within the key scope; keys created with descendants=false get 403 forbidden).
sortquerystringone of id | name | -id | -nameidAscending, or descending with a - prefix. Always tie-broken on id.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/{alias}/{id}/teams" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /{alias}/{id}/players

https://api.4league.app/v1/{alias}/{id}/players players:read

Aliases for {alias}: organizations, federations, associations, clubs.

With includeDescendants=true and more than 50 organizations in scope, one of clubId, associationId, competitionId, teamId is required, otherwise 422 scopeTooLarge with details.requiresOneOf.

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
aliaspathstringone of organizations | federations | associations | clubs–Organization type alias, see Organization aliases.
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
associationIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
clubIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
competitionIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
teamIdqueryobjectId––24-character hex id. Must be in the key scope and of the right type, otherwise 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
statusquerystringone of active | inactive–
includeDescendantsquerybooleanone of true | falsefalseInclude organizations below the addressed one (only within the key scope; keys created with descendants=false get 403 forbidden).
sortquerystringone of id | name | -id | -nameidAscending, or descending with a - prefix. Always tie-broken on id.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/{alias}/{id}/players" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

Tournaments

GET HEAD /tournaments/{id}

https://api.4league.app/v1/tournaments/{id} competitions:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/tournaments/{tournamentId}" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/tournaments/{tournamentId}), HTTP 200.

{
  "data": {
    "competition": {
      "id": "6acddc3d41a6e2f5682625e6",
      "name": "c-6acddc3d41a6e2f5682625e6",
      "logo": null,
      "type": "league",
      "season": 3,
      "stage": "regular",
      "timezone": "UTC",
      "gender": null,
      "completed": false,
      "hasPlayoff": false,
      "hasPlayout": false,
      "groupCount": 2
    }
  }
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /tournaments/{id}/matches

https://api.4league.app/v1/tournaments/{id}/matches matches:read

Matches of the requested competition only (playoff/playout child competitions are not included, see knownLimitations).

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
fromqueryiso8601––Inclusive lower bound on kickoff, see timeFilters.
toqueryiso8601––Inclusive upper bound on kickoff, see timeFilters.
statusquerystringone of upcoming | live | finished | postponed–Match status filter.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/tournaments/{tournamentId}/matches?from=2026-01-05&to=2026-01-05&limit=2" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/tournaments/{tournamentId}/matches?from=2026-01-05&to=2026-01-05&limit=2), HTTP 200.

{
  "data": [
    {
      "id": "6acddc3d41a6e2f5682625ef",
      "status": "finished",
      "kickoffAt": "2026-01-05T12:00:00.000Z",
      "home": {
        "id": "6acddc3d41a6e2f5682625e8",
        "name": "TeamA",
        "shortName": "TEA",
        "logo": null
      },
      "away": {
        "id": "6acddc3d41a6e2f5682625ea",
        "name": "TeamB",
        "shortName": "TEA",
        "logo": null
      },
      "score": {
        "home": 1,
        "away": 1
      },
      "penalties": null,
      "leg": null,
      "twoLegs": false,
      "winner": "draw",
      "round": 1,
      "group": null
    }
  ],
  "page": 1,
  "limit": 2,
  "total": 1,
  "hasMore": false,
  "competition": {
    "id": "6acddc3d41a6e2f5682625e6",
    "name": "c-6acddc3d41a6e2f5682625e6",
    "logo": null,
    "type": "league",
    "season": 3,
    "stage": "regular",
    "timezone": "UTC"
  }
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /tournaments/{id}/standings

https://api.4league.app/v1/tournaments/{id}/standings standings:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/tournaments/{tournamentId}/standings" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/tournaments/{tournamentId}/standings), HTTP 200.

{
  "data": {
    "competition": {
      "id": "6acddc3d41a6e2f5682625e6",
      "name": "c-6acddc3d41a6e2f5682625e6",
      "logo": null,
      "type": "league",
      "season": 3,
      "stage": "regular",
      "timezone": "UTC"
    },
    "standings": [
      {
        "rank": 1,
        "team": {
          "id": "6acddc3d41a6e2f5682625e8",
          "name": "TeamA",
          "shortName": "TEA",
          "logo": null
        },
        "played": 1,
        "won": 0,
        "drawn": 1,
        "lost": 0,
        "goalsFor": 1,
        "goalsAgainst": 1,
        "goalDiff": 0,
        "points": 1,
        "startingPoints": 0,
        "group": null
      }
    ],
    "playoffStandings": null,
    "playoutStandings": null,
    "playoffFormat": null,
    "playoutFormat": null,
    "playoffCompleted": null,
    "playoutCompleted": null
  }
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /tournaments/{id}/groups

https://api.4league.app/v1/tournaments/{id}/groups competitions:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/tournaments/{id}/groups" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /tournaments/{id}/teams

https://api.4league.app/v1/tournaments/{id}/teams teams:read

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/tournaments/{id}/teams" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /tournaments/{id}/players

https://api.4league.app/v1/tournaments/{id}/players players:read

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/tournaments/{id}/players" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /tournaments/{id}/statistics

https://api.4league.app/v1/tournaments/{id}/statistics competitions:read players:read

Player-level rows, so both scopes are required.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/tournaments/{id}/statistics" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /tournaments/{id}/top-scorers

https://api.4league.app/v1/tournaments/{id}/top-scorers players:read

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
typequerystringone of goals | assists | appearances–Ranking kind; default goals.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/tournaments/{id}/top-scorers" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /tournaments/{id}/cards

https://api.4league.app/v1/tournaments/{id}/cards players:read

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
scopequerystringone of player | team–Rows per player or per team; default player.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/tournaments/{id}/cards" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

Matches

GET HEAD /matches/{id}

https://api.4league.app/v1/matches/{id} matches:read

Friendlies (no competition) are returned when home or away is in scope. season, when set, must be the current season of the match competition.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/matches/{matchId}" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/matches/{matchId}), HTTP 200.

{
  "data": {
    "competition": {
      "id": "6acddc3d41a6e2f5682625e6",
      "name": "c-6acddc3d41a6e2f5682625e6",
      "logo": null,
      "type": "league",
      "season": 3,
      "stage": "regular",
      "timezone": "UTC"
    },
    "match": {
      "id": "6acddc3d41a6e2f5682625ef",
      "status": "finished",
      "kickoffAt": "2026-01-05T12:00:00.000Z",
      "home": {
        "id": "6acddc3d41a6e2f5682625e8",
        "name": "TeamA",
        "shortName": "TEA",
        "logo": null
      },
      "away": {
        "id": "6acddc3d41a6e2f5682625ea",
        "name": "TeamB",
        "shortName": "TEA",
        "logo": null
      },
      "score": {
        "home": 1,
        "away": 1
      },
      "penalties": null,
      "leg": null,
      "twoLegs": false,
      "winner": "draw",
      "round": 1,
      "group": null
    }
  }
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /matches/{id}/lineups

https://api.4league.app/v1/matches/{id}/lineups matches:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/matches/{id}/lineups" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /matches/{id}/events

https://api.4league.app/v1/matches/{id}/events matches:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/matches/{id}/events" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /matches/{id}/statistics

https://api.4league.app/v1/matches/{id}/statistics matchStatistics:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/matches/{id}/statistics" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

Teams

GET HEAD /teams/{id}

https://api.4league.app/v1/teams/{id} teams:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.

Example request

curl -sS "https://api.4league.app/v1/teams/{id}" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /teams/{id}/players

https://api.4league.app/v1/teams/{id}/players players:read

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/teams/{teamId}/players?limit=2" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/teams/{teamId}/players?limit=2), HTTP 200.

{
  "data": [
    {
      "id": "6acddc3d41a6e2f5682625eb",
      "name": "PlayerAna",
      "number": 9,
      "position": null,
      "photo": "https://cdn.test/photos/ana.png",
      "teamId": "6acddc3d41a6e2f5682625e7"
    }
  ],
  "page": 1,
  "limit": 2,
  "total": 1,
  "hasMore": false
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /teams/{id}/matches

https://api.4league.app/v1/teams/{id}/matches matches:read

from/to are always compared in UTC. A club id expands to the club and its most recent competition copies; when capped the response carries meta.truncated:true and meta.competitionsIncluded.

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
fromqueryiso8601––Inclusive lower bound on kickoff, see timeFilters.
toqueryiso8601––Inclusive upper bound on kickoff, see timeFilters.
statusquerystringone of upcoming | live | finished | postponed–Match status filter.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/teams/{id}/matches" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /teams/{id}/statistics

https://api.4league.app/v1/teams/{id}/statistics teams:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/teams/{id}/statistics" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

Players

GET HEAD /players/{id}

https://api.4league.app/v1/players/{id} players:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.

Example request

curl -sS "https://api.4league.app/v1/players/{playerId}" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

Example response

Captured from a seeded test organization (GET /v1/players/{playerId}), HTTP 200.

{
  "data": {
    "player": {
      "id": "6acddc3d41a6e2f5682625eb",
      "name": "PlayerAna",
      "number": 9,
      "position": null,
      "photo": "https://cdn.test/photos/ana.png",
      "team": {
        "id": "6acddc3d41a6e2f5682625e7",
        "name": "TeamA",
        "shortName": "TEA",
        "logo": "https://cdn.test/team-a.png"
      }
    }
  }
}

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /players/{id}/statistics

https://api.4league.app/v1/players/{id}/statistics players:read

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.

Example request

curl -sS "https://api.4league.app/v1/players/{id}/statistics" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

GET HEAD /players/{id}/matches

https://api.4league.app/v1/players/{id}/matches matches:read

from/to are always compared in UTC.

Paginated: returns the pagination envelope.

Parameters

NameInTypeAllowedDefaultDescription
idpathobjectId––Resource id (24-character hex). A malformed id answers 404 notFound.
seasonqueryinteger––Positive integer, at most 9 digits. Archived season for data routes; absent = current season.
fromqueryiso8601––Inclusive lower bound on kickoff, see timeFilters.
toqueryiso8601––Inclusive upper bound on kickoff, see timeFilters.
statusquerystringone of upcoming | live | finished | postponed–Match status filter.
pagequeryintegermin 11Page number, 1-based.
limitqueryintegermin 1, max 10025Items per page.

Example request

curl -sS "https://api.4league.app/v1/players/{id}/matches" \
  -H "X-4League-Key: $FOURLEAGUE_KEY_ID" \
  -H "X-4League-Timestamp: $TS" \
  -H "X-4League-Nonce: $NONCE" \
  -H "X-4League-Signature: $SIG"

No captured example for this endpoint yet.

Possible errors

Listed errors are the ones that can apply based on the endpoint's parameters; see Errors for the full table.

Known limitations

  • Only organization-scoped keys are documented. Competition-scoped keys are a known limitation and are not part of this description.
  • Playoff and playout matches are known limitations: /tournaments/{id}/matches lists the requested competition only. Standings expose the playoff/playout tables.
  • The organization tree follows the primary parent only; an organization reachable only through an additional parent can be fetched directly but is absent from the tree.
  • Season filters on organization lists cover the live season only; archived seasons are not searched.
  • The rate limiter and the failed-authentication block are per server worker, so limits are approximate.