The dual-ID model
Every Football V2 competition is identified by two numeric IDs that look interchangeable but are not. uniqueTournament.id is the canonical, season-independent identifier for a league or competition. tournament.id is a per-season, per-group variant that changes every year and is only meaningful when paired with a seasonId.
Mixing them up is the single most common cause of broken integrations — IDs that worked last season silently stop resolving when the new season rolls over.
Side-by-side
Worked example
A trimmed /api/event/{id} response shows both fields side by side:
tournament.uniqueTournament.id = 17 → store this. It will still be 17 in 2030.
tournament.id = 1 → never store this. Next season it’s a different number.
season.id = 76986 → discover dynamically via /api/tournaments/17/seasons whenever you need season-scoped data.
Confirmed canonical IDs (top competitions)
If you’ve seen a different ID for one of these in the wild (e.g. 49 for FA Cup, 1 for Premier League, 104 for MLS), you were looking at the per-season tournament.id, not the canonical one.
When to use which
Use uniqueTournament.id when:
- Storing a competition reference in your database
- Filtering matches, fixtures, or teams by competition
- Loading a league logo via
/images/tournaments/{id}
- Querying competition-level metadata that doesn’t depend on the current season
Use tournament.id (paired with seasonId) only when:
- Calling season-scoped endpoints such as:
/api/tournament/{tournamentId}/season/{seasonId}/standings
/api/tournament/{tournamentId}/season/{seasonId}/top-players/...
/api/tournament/{tournamentId}/season/{seasonId}/cuptrees
And in those cases, resolve tournament.id and seasonId dynamically every time — don’t cache them past a single season.
Resolution flow
The tournamentId for the season-scoped call comes from the same seasons response — never hardcode it.
Anti-pattern
Never persist tournament.id as a foreign key. It will silently break at the next season rollover when SportsAPI Pro regenerates per-season IDs. Every integration that hits us with “the league suddenly stopped working in August” has done exactly this.