kali-afl get api key →

AFL Stats API

A versioned, key-authenticated REST API for AFL match results, player statistics, team data, leaderboards, and more. All responses are JSON.

Current version: v1

Authentication

Every request (except Fixture) requires an API key passed via the Authorization header as a Bearer token. Keys are managed on the API Usage page after signing in. Get a free API key →

Header Format

Authorization: Bearer YOUR_API_KEY

Example

curl https://kaliaflstats.com/api/afl/v1/teams \
  -H "Authorization: Bearer a3f9c2d1e8..."

Base URL

https://kaliaflstats.com/api/afl/v1

All endpoint paths below are relative to this base. When running locally, use http://localhost:5173.

Response Format

All successful responses wrap data in a consistent envelope. List endpoints include a meta object for pagination. Single-resource endpoints return { "data": { ... } }.

List Response

{
  "data": [ ... ],
  "meta": {
    "limit":  50,
    "offset": 0,
    "count":  10,
    "total":  142
  }
}

Single Resource Response

{
  "data": {
    "id": "sydney-swans",
    "name": "Sydney Swans",
    "shortName": "SYD"
  }
}

Pagination

All list endpoints support limit and offset query parameters.

ParameterDefaultRangeDescription
limit501 -- 200Number of records to return
offset00+Number of records to skip

To iterate all records, keep fetching pages until offset + meta.count >= meta.total.

# Page 1
GET /players?limit=50&offset=0

# Page 2
GET /players?limit=50&offset=50

# Page 3
GET /players?limit=50&offset=100

Sorting

The player-stats and player-stats-advanced endpoints support dynamic sorting via sort_by and order query parameters.

ParameterTypeDescription
sort_bystringColumn to sort by (see valid values per endpoint)
orderstringasc or desc (default: desc)
# Top goal scorers in 2024, round 10
GET /player-stats?year=2024&round=10&sort_by=goals&order=desc

Errors

Error responses always include an error string.

StatusBodyMeaning
400{"error":"Bad request: ..."}Invalid or malformed query parameter
401{"error":"Unauthorized"}Missing, invalid, or revoked API key
404{"error":"... not found"}Resource with the given ID does not exist
429{"error":"Rate limit exceeded"}Your key's request limit has been reached

Endpoints

Teams

GET /teams

Returns all 18 AFL teams, ordered alphabetically.

Query Parameters

NameTypeRequiredDescription
limitintegerNoDefault 50, max 200
offsetintegerNoDefault 0

Example

curl /api/afl/v1/teams -H "Authorization: Bearer YOUR_KEY"

Response

{
  "data": [
    { "id": "adelaide-crows", "name": "Adelaide Crows", "shortName": "ADL" },
    { "id": "brisbane-lions", "name": "Brisbane Lions", "shortName": "BRL" }
  ],
  "meta": { "limit": 50, "offset": 0, "count": 18, "total": 18 }
}
GET /teams/:id

Returns a single team by its slug ID.

Path Parameters

NameTypeDescription
idstringTeam slug, e.g. sydney-swans

Example

curl /api/afl/v1/teams/sydney-swans -H "Authorization: Bearer YOUR_KEY"

Response

{
  "data": { "id": "sydney-swans", "name": "Sydney Swans", "shortName": "SYD" }
}
GET /teams/:id/stats

Returns aggregated team statistics per match. Each row sums all player stats for that team in a single match. Useful for comparing team-level performance across a season.

Parameters

NameTypeRequiredDescription
idstringYes (path)Team slug
yearintegerNoFilter by season year
roundintegerNoFilter by round
limitintegerNoDefault 50, max 200
offsetintegerNoDefault 0

Example

curl "/api/afl/v1/teams/sydney-swans/stats?year=2024" \
  -H "Authorization: Bearer YOUR_KEY"

Response

{
  "data": [
    {
      "matchId": 9812, "round": 5, "year": 2024,
      "opponent": "Greater Western Sydney", "opponentShortName": "GWS",
      "isHome": true, "teamScore": 104, "opponentScore": 87,
      "kicks": 210, "handballs": 158, "disposals": 368,
      "marks": 95, "goals": 16, "behinds": 8,
      "tackles": 62, "hitouts": 38, ...
    }
  ],
  "meta": { "limit": 50, "offset": 0, "count": 22, "total": 22 }
}

Players

GET /players

Returns players ordered alphabetically. Filter by team, search by name, or filter by season year (players who appeared in at least one match that year).

Query Parameters

NameTypeRequiredDescription
team_idstringNoFilter by current team slug
namestringNoPartial name search (case-insensitive)
yearintegerNoOnly players who played in this season
limitintegerNoDefault 50, max 200
offsetintegerNoDefault 0

Examples

# Search for a player by name
GET /players?name=warner

# All Collingwood players who played in 2024
GET /players?team_id=collingwood&year=2024

Response

{
  "data": [
    { "id": 144, "name": "Chad Warner", "currentTeamId": "sydney-swans", "onlineId": "12345" }
  ],
  "meta": { "limit": 50, "offset": 0, "count": 1, "total": 1 }
}
GET /players/:id

Returns a single player by numeric ID.

Example

curl /api/afl/v1/players/144 -H "Authorization: Bearer YOUR_KEY"

Response

{
  "data": { "id": 144, "name": "Chad Warner", "currentTeamId": "sydney-swans", "onlineId": "12345" }
}
GET /players/:id/career

Returns career totals and per-game averages for a player across all seasons in the database.

Example

curl /api/afl/v1/players/144/career -H "Authorization: Bearer YOUR_KEY"

Response

{
  "data": {
    "playerId": 144,
    "playerName": "Chad Warner",
    "currentTeamId": "sydney-swans",
    "gamesPlayed": 85,
    "totals": { "kicks": 1020, "handballs": 780, "disposals": 1800, ... },
    "averages": { "kicks": 12.0, "handballs": 9.18, "disposals": 21.18, ... }
  }
}
GET /players/:id/season

Returns season totals and per-game averages for a player in a specific year.

Query Parameters

NameTypeRequiredDescription
yearintegerYesSeason year

Example

curl "/api/afl/v1/players/144/season?year=2024" -H "Authorization: Bearer YOUR_KEY"

Response shape is identical to /players/:id/career but scoped to the given year.

Matches

GET /matches

Returns matches with scores, teams, venue, and crowd. Ordered newest first (year desc, round desc).

Query Parameters

NameTypeRequiredDescription
yearintegerNoFilter by season year
roundintegerNoFilter by round (0 = finals)
team_idstringNoMatches involving this team (home or away)
venuestringNoFilter by venue name (exact match)
date_fromstringNoISO date, e.g. 2024-01-01
date_tostringNoISO date (inclusive)
limitintegerNoDefault 50, max 200
offsetintegerNoDefault 0

Examples

# All Sydney Swans matches in 2024
GET /matches?team_id=sydney-swans&year=2024

# Matches at the MCG in a date range
GET /matches?venue=MCG&date_from=2024-06-01&date_to=2024-06-30

# Round 10, 2024
GET /matches?year=2024&round=10

Response

{
  "data": [
    {
      "id": 9812, "round": 5, "year": 2024,
      "homeTeam": "Sydney Swans", "homeShortName": "SYD",
      "awayTeam": "Greater Western Sydney", "awayShortName": "GWS",
      "homeScore": 104, "awayScore": 87,
      "venue": "SCG", "date": "2024-04-20T13:45:00",
      "crowd": 38214, "sourcedAt": "2024-04-21T00:12:44.231Z"
    }
  ],
  "meta": { "limit": 50, "offset": 0, "count": 9, "total": 9 }
}
GET /matches/:id

Returns a single match by numeric ID.

Example

curl /api/afl/v1/matches/9812 -H "Authorization: Bearer YOUR_KEY"

Response shape is the same as a single item from GET /matches, wrapped in { "data": { ... } }.

Player Stats

GET /player-stats

Returns per-match player statistics (17 categories). Each row is one player in one match. At least one filter is recommended.

Query Parameters

NameTypeRequiredDescription
match_idintegerNoFilter by match ID
player_idintegerNoFilter by player ID
yearintegerNoFilter by season year
roundintegerNoFilter by round
team_idstringNoFilter by team slug
sort_bystringNoSort column (default: disposals)
orderstringNoasc or desc (default: desc)
limitintegerNoDefault 50, max 200
offsetintegerNoDefault 0

Valid sort_by values

kicks, handballs, disposals, marks, goals, behinds, tackles, hitouts,
goal_assists, inside_50s, clearances, clangers, rebound_50s,
frees_for, frees_against, afl_fantasy_pts, supercoach_pts

Examples

# All stats for a single match
GET /player-stats?match_id=9812

# One player's 2024 season, sorted by fantasy points
GET /player-stats?player_id=144&year=2024&sort_by=afl_fantasy_pts

# Top tacklers in round 10
GET /player-stats?year=2024&round=10&sort_by=tackles&limit=10

Response

{
  "data": [
    {
      "matchId": 9812, "playerName": "Chad Warner", "teamId": "sydney-swans",
      "kicks": 18, "handballs": 14, "disposals": 32,
      "marks": 6, "goals": 1, "behinds": 0,
      "tackles": 5, "hitouts": 0, "goalAssists": 2,
      "inside50s": 7, "clearances": 8, "clangers": 3,
      "rebound50s": 1, "freesFor": 2, "freesAgainst": 1,
      "aflFantasyPts": 118, "supercoachPts": 124
    }
  ],
  "meta": { "limit": 50, "offset": 0, "count": 44, "total": 44 }
}

Stat Fields Reference

FieldDescription
kicksKicks
handballsHandballs
disposalsTotal disposals (kicks + handballs)
marksMarks
goalsGoals scored
behindsBehinds scored
tacklesTackles
hitoutsHitouts (ruck contests)
goalAssistsGoal assists
inside50sInside 50s
clearancesClearances
clangersClangers (turnover errors)
rebound50sRebound 50s
freesForFrees for (free kicks awarded)
freesAgainstFrees against (free kicks conceded)
aflFantasyPtsAFL Fantasy points
supercoachPtsSuperCoach points

Player Stats (Advanced)

GET /player-stats-advanced

Returns advanced per-match player statistics (17 categories) including contested possessions, disposal efficiency, metres gained, and more.

Query Parameters

Same filter parameters as /player-stats: match_id, player_id, year, round, team_id, sort_by, order, limit, offset.

Valid sort_by values

contested_possessions, uncontested_possessions, effective_disposals,
disposal_efficiency_pct, contested_marks, goal_assists, marks_inside_50,
one_percenters, bounces, centre_clearances, stoppage_clearances,
score_involvements, metres_gained, turnovers, intercepts,
tackles_inside_50, time_on_ground_pct

Example

# Highest metres gained in round 10, 2024
GET /player-stats-advanced?year=2024&round=10&sort_by=metres_gained&limit=10

Advanced Stat Fields Reference

FieldDescription
contestedPossessionsContested possessions
uncontestedPossessionsUncontested possessions
effectiveDisposalsEffective disposals
disposalEfficiencyPctDisposal efficiency (percentage)
contestedMarksContested marks
goalAssistsGoal assists
marksInside50Marks inside 50
onePercentersOne percenters
bouncesBounces
centreClearancesCentre clearances
stoppageClearancesStoppage clearances
scoreInvolvementsScore involvements
metresGainedMetres gained
turnoversTurnovers
interceptsIntercepts
tacklesInside50Tackles inside 50
timeOnGroundPctTime on ground (percentage)

Player Team Assignments

GET /player-team-assignments

Returns player transfer and movement history. Each row represents a period at a club. An open-ended endYear: null means the player is currently at that club.

Query Parameters

NameTypeRequiredDescription
player_idintegerNoAll clubs a player has been at
team_idstringNoAll players at a club
yearintegerNoAssignments active during this year
reasonstringNoMovement type: trade, rookie, delisted, etc.
limitintegerNoDefault 50, max 200
offsetintegerNoDefault 0

Examples

# Full club history for a player
GET /player-team-assignments?player_id=144

# All trades into Collingwood
GET /player-team-assignments?team_id=collingwood&reason=trade

Response

{
  "data": [
    {
      "id": 301, "playerName": "Chad Warner", "playerId": 144,
      "teamId": "sydney-swans", "teamName": "Sydney Swans",
      "startYear": 2021, "endYear": null, "reason": "rookie"
    }
  ],
  "meta": { "limit": 50, "offset": 0, "count": 1, "total": 1 }
}

Leaderboards

GET /leaderboards

Returns the top players ranked by any basic stat column, ordered descending. Ideal for "who had the most goals in round X?" style queries.

Query Parameters

NameTypeRequiredDescription
statstringYesStat to rank by (see valid values below)
yearintegerNoFilter by season year
roundintegerNoFilter by round
team_idstringNoFilter to a single team's players
limitintegerNoDefault 50, max 200
offsetintegerNoDefault 0

Valid stat values

kicks, handballs, disposals, marks, goals, behinds, tackles, hitouts,
goal_assists, inside_50s, clearances, clangers, rebound_50s,
frees_for, frees_against, afl_fantasy_pts, supercoach_pts

Examples

# Top 10 disposal getters in 2024
GET /leaderboards?stat=disposals&year=2024&limit=10

# Highest goal tallies in round 5 for Sydney
GET /leaderboards?stat=goals&year=2024&round=5&team_id=sydney-swans

Response

{
  "data": [
    { "playerId": 144, "playerName": "Chad Warner", "teamId": "sydney-swans", "value": 32 },
    { "playerId": 201, "playerName": "Marcus Bontempelli", "teamId": "western-bulldogs", "value": 31 }
  ],
  "meta": { "limit": 10, "offset": 0, "count": 10, "total": 4820 }
}

Head-to-Head

GET /head-to-head

Returns the match history between two teams, regardless of which was home or away.

Query Parameters

NameTypeRequiredDescription
team_astringYesFirst team slug
team_bstringYesSecond team slug
yearintegerNoFilter to a specific season
venuestringNoFilter to a specific venue
limitintegerNoDefault 50, max 200
offsetintegerNoDefault 0

Example

# Swans vs Magpies all-time at the SCG
GET /head-to-head?team_a=sydney-swans&team_b=collingwood&venue=SCG

Response is a standard paginated list of match objects (same shape as GET /matches).

Venues

GET /venues

Returns all venues in the database with match counts, ordered by most matches. Useful for getting valid venue values for the venue filter on other endpoints.

Example

curl /api/afl/v1/venues -H "Authorization: Bearer YOUR_KEY"

Response

{
  "data": [
    { "venue": "MCG", "matchCount": 412 },
    { "venue": "Marvel Stadium", "matchCount": 298 },
    { "venue": "SCG", "matchCount": 186 }
  ],
  "meta": { "count": 24 }
}

Standings

GET /standings

Returns the season ladder for a given year: wins, losses, draws, points for/against, percentage, and premiership points. Ordered by premiership points then percentage.

Query Parameters

NameTypeRequiredDescription
yearintegerYesSeason year

Example

curl "/api/afl/v1/standings?year=2024" -H "Authorization: Bearer YOUR_KEY"

Response

{
  "data": [
    {
      "teamId": "sydney-swans", "teamName": "Sydney Swans", "teamShortName": "SYD",
      "played": 24, "wins": 17, "losses": 6, "draws": 1,
      "pointsFor": 2156, "pointsAgainst": 1742,
      "percentage": 123.77, "premiershipsPoints": 70
    }
  ],
  "meta": { "year": 2024, "count": 18 }
}

Tips

GET /tips

Returns tipster win-probability predictions for each game in a given round, sourced from Squiggle. Each row is one tipster's prediction for one match.

Query Parameters

NameTypeRequiredDescription
yearintegerYesSeason year
roundintegerYesRound number

Example

curl "/api/afl/v1/tips?year=2026&round=4" -H "Authorization: Bearer YOUR_KEY"

Response

{
  "data": [
    {
      "id": 1, "gameId": 38201, "year": 2026, "round": 4,
      "hteam": "Sydney Swans", "ateam": "Collingwood",
      "hconfidence": 62, "source": "Squiggle",
      "syncedAt": "2026-04-06T12:00:00.000Z"
    }
  ],
  "meta": { "year": 2026, "round": 4, "count": 9 }
}

Fixture (Public)

GET /fixture Public

Returns the season fixture (schedule) sourced from the Squiggle API. This is the only endpoint that does not require authentication.

Query Parameters

NameTypeRequiredDescription
yearintegerNoSeason year (default: current year). Range: 2000 to next year.

Example

# No auth required
curl /api/afl/v1/fixture?year=2026

Response

{
  "year": 2026,
  "games": [ ... ]  // Squiggle fixture data
}

Quick Reference

All endpoints at a glance. All require auth unless noted.

MethodPathDescription
GET/teamsList all teams
GET/teams/:idGet single team
GET/teams/:id/statsAggregated team stats per match
GET/playersList players (search, filter)
GET/players/:idGet single player
GET/players/:id/careerCareer totals + averages
GET/players/:id/seasonSeason totals + averages
GET/matchesList matches (filter by team, venue, dates)
GET/matches/:idGet single match
GET/player-statsPer-match player stats (sortable)
GET/player-stats-advancedPer-match advanced stats (sortable)
GET/player-team-assignmentsTransfer / movement history
GET/leaderboardsTop players by any stat
GET/head-to-headMatch history between two teams
GET/venuesAll venues with match counts
GET/standingsSeason ladder
GET/tipsWin-probability tips by round
GET/fixtureSeason schedule (Public — no auth)

Ready to start building?

get a free api key →