Build a league page#
This guide walks the exact API workflow behind a league page like the ones on this site: header, standings table, fixtures list, results, top scorers and a best XI. We use the Argentine Liga Profesional as the worked example — swap in any league id and it works the same.
All endpoints here are on the free football API. Full parameter reference: Leagues, seasons & standings.
1. Find the league id#
Search the league list once and store the id — ids are stable.
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/api/v2/leagues/?country=Argentina"
{
"count": 1,
"results": [
{ "id": 85, "name": "Liga Profesional de Fútbol", "country": "Argentina", "is_women": false }
]
}
Our league id is 85.
2. Resolve the current season#
Never hardcode a season — fetch the current one at page load (or cache it for a day):
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/api/v2/leagues/85/season/"
{ "id": 1635, "name": "Primera LPF 2026", "year": 2026,
"start_date": "2026-01-01", "end_date": "2026-12-31", "is_current": true }
Current season id: 1635. If you need a season picker, list all of them
with GET /api/v2/leagues/85/seasons/.
3. Standings#
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/api/v2/leagues/85/standings/?season_id=1635"
Rows include position, team id + name, played, W/D/L, goals for/against,
points and recent form. Some competitions return a groups array instead of
a single table — render each group separately when present.
4. Fixtures and results#
Filter the events list by season_id. Combine with status and date ranges
for tabs:
# Next matches (upcoming, from today onwards)
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/api/v2/events/?season_id=1635&status=upcoming&date_from=2026-08-02&limit=20"
# Latest results
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/api/v2/events/?season_id=1635&status=finished&limit=20"
# Matchday grouping: use round_number / round_name on each event
Each event carries round_number, round_name and group_name, so you can
group the list by matchday without extra requests.
For live scores on the page, poll GET /api/v2/events/live/?league_id=85
every ~10 s, or subscribe to the football WebSocket
for push updates.
5. Top scorers and other leaderboards#
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/api/v2/leagues/85/top/scorers/?season_id=1635&limit=10"
The {stat} segment accepts scorers, assists, yellowcards, redcards
or fouls (default 20 rows, max 50). If you omit season_id it defaults to
the current season. Each row includes player_id — link it to a
player profile.
6. Best XI of the season (or of a matchday)#
# Season best XI
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/api/v2/leagues/85/bestxi/1635/"
# Matchday 5 best XI
curl -H "Authorization: Token YOUR_API_KEY" \
"https://sports.bzzoiro.com/api/v2/leagues/85/bestxi/1635/5/"
7. Logos and badges#
Use the Image API with the same ids — no extra lookups:
https://sports.bzzoiro.com/img/league/85/ league logo
https://sports.bzzoiro.com/img/team/755/ team badge (River Plate)
https://sports.bzzoiro.com/img/team/755/?bg=transparent
Putting it together#
A league page needs exactly five requests on first load, all cacheable:
| Section | Request | Suggested cache |
|---|---|---|
| Header | /api/v2/leagues/85/ |
1 day |
| Season resolve | /api/v2/leagues/85/season/ |
1 day |
| Standings | /api/v2/leagues/85/standings/?season_id=1635 |
10 min |
| Fixtures/results | /api/v2/events/?season_id=1635&... |
60 s |
| Top scorers | /api/v2/leagues/85/top/scorers/?season_id=1635 |
10 min |
Note: league and season ids never change mid-season, standings change only after matches — cache aggressively and your page stays well inside the rate limits.