Tournament Endpoints

Everything about a tournament: the event itself, its standings, its army lists and its battles.

List published tournaments, newest start date first. The date range is optional — leave it out and you get the most recent tournaments.

Query Parameters

ParameterTypeRequiredDescription
fromstringOptionalOnly tournaments starting on or after this date. Leave out for no lower bound.
tostringOptionalOnly tournaments starting on or before this date. Leave out for no upper bound. Give both and the window may not be longer than a year.
statusstringOptionalOnly tournaments with this status: "planned", "ongoing" or "finished".
cursorstringOptionalComes from the "next" link of a previous response. You never build this yourself.
limitintegerOptionalResults per page. Default: 20, max: 100.

Response Fields (per tournament)

slugstring
Short name used in the tournament web address. Use it wherever an endpoint asks for {slug}.
namestring
Tournament name.
status"planned" | "ongoing" | "finished"
Where the tournament has got to.
startDatestring (YYYY-MM-DD) | null
First day of the tournament, as a local date at the venue.
endDatestring (YYYY-MM-DD) | null
Last day of the tournament, as a local date at the venue.
descriptionstring
The description the organiser wrote, as plain text.
citystring | null
Town or city.
countrystring | null
Country name.
playersnumber
How many players are signed up.
roundsnumber
Total number of rounds, counting every stage.
battleSizenumber
Points limit per army, for example 2000.
battlePackstring | null
Name of the battle pack the tournament is played with.
organizerstring | null
Slug of the club running the tournament, or null when no club is set. Pass it to the club endpoints.See Club
tournamentOrganizers{name, playerId}[]
The people running the tournament, each with a display name and the public player id, sorted by name. These are the organisers themselves, not the club they run it for — that is organizer above. Empty when nobody is listed. Use a player id to get that player's battles.See GET /api/v1/users/{publicId}/battles
stagesStage[]
The stages the tournament is played in, in the order they run.
urlstring
Link to the tournament page on milarki.com.

Example response

json
{
  "data": [
    {
      "slug": "the-behemoth",
      "name": "The Behemoth",
      "status": "finished",
      "startDate": "2025-01-14",
      "endDate": "2025-01-15",
      "description": "Two days of Age of Sigmar in Hammarö.",
      "city": "Hammarö",
      "country": "Sweden",
      "players": 6,
      "rounds": 8,
      "battleSize": 2000,
      "battlePack": "GHB 24/25 4th",
      "organizer": "boebbens-club",
      "tournamentOrganizers": [
        {"name": "Björn Böbb", "playerId": "T91FKD3V"},
        {"name": "Sara Sköld", "playerId": "K21XQ9PB"}
      ],
      "stages": [
        {"id": "standings", "name": "Final Standings", "type": "board"},
        {"id": "swiss", "name": "Swiss Stage", "type": "board", "rounds": 5},
        {"id": "knockout", "name": "Knockout Stage", "type": "bracket", "rounds": 3, "players": 8}
      ],
      "url": "https://www.milarki.com/tournaments/the-behemoth"
    }
  ],
  "next": "https://milarki.com/api/v1/tournaments?cursor=eyJpZCI6Im5leHQifQ&limit=20"
}

Get one tournament. Exactly the same shape as a tournament in the list above.

Path Parameters

ParameterTypeRequiredDescription
slugstringRequiredThe short name from the tournament web address.

Response Fields

slugstring
Short name used in the tournament web address. Use it wherever an endpoint asks for {slug}.
namestring
Tournament name.
status"planned" | "ongoing" | "finished"
Where the tournament has got to.
startDatestring (YYYY-MM-DD) | null
First day of the tournament, as a local date at the venue.
endDatestring (YYYY-MM-DD) | null
Last day of the tournament, as a local date at the venue.
descriptionstring
The description the organiser wrote, as plain text.
citystring | null
Town or city.
countrystring | null
Country name.
playersnumber
How many players are signed up.
roundsnumber
Total number of rounds, counting every stage.
battleSizenumber
Points limit per army, for example 2000.
battlePackstring | null
Name of the battle pack the tournament is played with.
organizerstring | null
Slug of the club running the tournament, or null when no club is set. Pass it to the club endpoints.See Club
tournamentOrganizers{name, playerId}[]
The people running the tournament, each with a display name and the public player id, sorted by name. These are the organisers themselves, not the club they run it for — that is organizer above. Empty when nobody is listed. Use a player id to get that player's battles.See GET /api/v1/users/{publicId}/battles
stagesStage[]
The stages the tournament is played in, in the order they run.
urlstring
Link to the tournament page on milarki.com.

Returns 404 if the tournament does not exist or is not published.

Example response

json
{
  "data": {
    "slug": "the-behemoth",
    "name": "The Behemoth",
    "status": "finished",
    "startDate": "2025-01-14",
    "endDate": "2025-01-15",
    "description": "Two days of Age of Sigmar in Hammarö.",
    "city": "Hammarö",
    "country": "Sweden",
    "players": 6,
    "rounds": 8,
    "battleSize": 2000,
    "battlePack": "GHB 24/25 4th",
    "organizer": "boebbens-club",
    "tournamentOrganizers": [
      {"name": "Björn Böbb", "playerId": "T91FKD3V"},
      {"name": "Sara Sköld", "playerId": "K21XQ9PB"}
    ],
    "stages": [
      {"id": "standings", "name": "Final Standings", "type": "board"},
      {"id": "swiss", "name": "Swiss Stage", "type": "board", "rounds": 5},
      {"id": "knockout", "name": "Knockout Stage", "type": "bracket", "rounds": 3, "players": 8},
      {"id": "placement-5-8", "name": "Placement #5–8", "type": "bracket", "rounds": 2}
    ],
    "url": "https://www.milarki.com/tournaments/the-behemoth"
  }
}

Get the standings for one stage of a tournament. A tournament can have several stages — the Swiss rounds, a knockout bracket, placement brackets — and each one has its own standings.

Path Parameters

ParameterTypeRequiredDescription
slugstringRequiredThe short name from the tournament web address.

Query Parameters

ParameterTypeRequiredDescription
stagestringOptionalWhich stage to read. Leave it out and you get the final standings once the tournament has finished, otherwise the stage that is furthest along.

Standings come back whole — there are no pages to work through. A board is one row per player and a bracket is a handful of matches, so you always get the lot in one go.

Stage Ids

Read the ids for a tournament from its stages list rather than guessing — a tournament only has the stages it is actually set up for.

The id is what you pass here, and it never changes. The name is what to put in front of people: it is word for word the label on the tab the organiser sees in Milarki, so a screen built on the API and the tournament page itself always agree. Do not build the name yourself from the id. The same swiss id comes back as Swiss Stage in one tournament and Group Stage in another, depending on how the organiser set it up — and a scoped board can carry a label of its own on top of that.

  • standings — the final standings, everything merged into one table. Only once the tournament has finished.
  • swiss — the main Swiss rounds.
  • knockout — the knockout bracket.
  • placement-swiss — the Swiss board played by everyone outside the knockout.
  • placement-3, placement-5-8, and so on — the small brackets that settle the remaining places, one per band.

Response

The response tells you which stage you got, then the rows. What the rows look like depends on the stage type: a board gives you a ranked table of players, a bracket gives you the matches instead, earliest round first.

Board Rows

ranknumber | null
Placement, 1 being first.
groupstring · optionalon group stage boards
Which group the player was in, for example "Group A".
playerstring | null
The player display name.
playerIdstring | null
The public player id, when the player has one. Use it to get that player's battles.See GET /api/v1/users/{publicId}/battles
factionstring | null
Faction played.
battlePointsnumber
Battle points earned, scored the way the organiser set up.
winsnumber
Battles won.
drawsnumber
Battles drawn.
lossesnumber
Battles lost.
victoryPointsnumber
Victory points scored across every battle.
victoryPointsDiffnumber
Victory points scored minus victory points given away.

Example response — a board stage

json
{
  "stage": {"id": "swiss", "name": "Swiss Stage", "type": "board"},
  "data": [
    {
      "rank": 1,
      "player": "Anders Larsson",
      "playerId": "L80MTI4R",
      "faction": "Slaves to Darkness",
      "battlePoints": 92,
      "wins": 4,
      "draws": 0,
      "losses": 1,
      "victoryPoints": 121,
      "victoryPointsDiff": 37
    }
  ]
}

Tournaments Played In Groups

When a tournament is set up with groups, the board gives you every group at once, ordered by group and then by position within it. Each row says which group the player was in. You know this is coming before you read a row: the stage comes back named Group Stage.

Two things about it look like mistakes and are not. Positions start again at 1 in each group, because a group really is its own board — whoever came first in Group B did not tie with whoever came first in Group A, they simply never played the same set of people. And group is absent altogether from an ordinary Swiss board, in the same way a battle only carries the scores its battle pack actually uses.

Example response — a tournament played in groups

json
{
  "stage": {"id": "swiss", "name": "Group Stage", "type": "board"},
  "data": [
    {
      "rank": 1,
      "group": "Group A",
      "player": "Anders Larsson",
      "playerId": "L80MTI4R",
      "faction": "Slaves to Darkness",
      "battlePoints": 92,
      "wins": 4,
      "draws": 0,
      "losses": 1,
      "victoryPoints": 121,
      "victoryPointsDiff": 37
    },
    {
      "rank": 2,
      "group": "Group A",
      "player": "Björn Nilsson",
      "playerId": "K21PQ7ZC",
      "faction": "Stormcast Eternals",
      "battlePoints": 78,
      "wins": 3,
      "draws": 0,
      "losses": 2,
      "victoryPoints": 104,
      "victoryPointsDiff": 12
    },
    {
      "rank": 1,
      "group": "Group B",
      "player": "Cecilia Berg",
      "playerId": "M53RTX9F",
      "faction": "Cities of Sigmar",
      "battlePoints": 88,
      "wins": 4,
      "draws": 1,
      "losses": 0,
      "victoryPoints": 118,
      "victoryPointsDiff": 41
    }
  ]
}

Bracket Matches

roundstring
Name of the bracket round, for example "Quarter-finals" or "Final".
tablenumber
Table number.
playersstring[]
The two player names. Empty while the match is still waiting on an earlier result.
winnerstring | null
Name of the player who went through. Null until the match has been played.
battlestring | null
Battle id to pass to /battles/{id}. Null when no battle was recorded for the match.See Battle

An unknown stage returns 404 with a message listing the ids this tournament does have.

Example response — a bracket stage

json
{
  "stage": {"id": "knockout", "name": "Knockout Stage", "type": "bracket"},
  "data": [
    {
      "round": "Quarter-finals",
      "table": 1,
      "players": ["Anders Larsson", "Björn Nilsson"],
      "winner": "Anders Larsson",
      "battle": "000b1161c8a864a1f75f"
    },
    {
      "round": "Semi-finals",
      "table": 1,
      "players": [],
      "winner": null,
      "battle": null
    }
  ]
}

Everybody taking part, in alphabetical order, each with the army list they submitted. This is the same data as the army list export in the admin.

Path Parameters

ParameterTypeRequiredDescription
slugstringRequiredThe short name from the tournament web address.

Query Parameters

ParameterTypeRequiredDescription
cursorstringOptionalComes from the "next" link of a previous response.
limitintegerOptionalResults per page. Default: 20, max: 100.

Response Fields (per participant)

playerstring
The player display name.
playerIdstring | null
The public player id, when the player has one. Use it to get that player's battles.See GET /api/v1/users/{publicId}/battles
clubstring | null
The club the player represents, as its short name from the club web address.See GET /api/v1/clubs/{slug}
groupstring | null
Which group the player was placed in, for example "Group A". Null unless the tournament has a group stage. Matches the group on a leaderboard row.See Leaderboard row
droppedboolean
True when the player is no longer taking part, either because they dropped out or never turned up.
finalPlacementnumber | null
Where the player finished, 1 being the winner. Settled once the tournament finishes; null while it is still running, and null for tournaments that finished before we started recording it.
listArmyList | null
The army the player submitted, or null when they submitted none.

Example response

json
{
  "data": [
    {
      "player": "Anders Larsson",
      "playerId": "L80MTI4R",
      "club": "stockholm-warlords",
      "group": "Group A",
      "dropped": false,
      "finalPlacement": 1,
      "list": {
        "faction": "Disciples of Tzeentch",
        "subFaction": "Guild of Summoners",
        "points": 1990,
        "battleTacticCards": ["Sever the Head", "Bring it Down"],
        "text": "Allegiance: Disciples of Tzeentch\n..."
      }
    }
  ],
  "next": null
}

Every battle played in the tournament, newest first.

Path Parameters

ParameterTypeRequiredDescription
slugstringRequiredThe short name from the tournament web address.

Query Parameters

ParameterTypeRequiredDescription
cursorstringOptionalComes from the "next" link of a previous response.
limitintegerOptionalResults per page. Default: 20, max: 100.

Response Fields (per battle)

idstring
The battle id. Pass it to /battles/{id}.
datestring (YYYY-MM-DD) | null
The day the battle was played, as a local date.
tournamentstring | null
Slug of the tournament the battle belongs to. Null for a casual battle.See Tournament
stagestring | null
Id of the tournament stage the battle was played in, for example "swiss". Null for a casual battle.See Stage
roundnumber | null
Round number, counting from 1.
scenariostring | null
Scenario played.
battlePackstring | null
Name of the battle pack the battle was played with.
battleSizenumber
Points limit per army, for example 2000.
winnerstring | null
Name of the winning player. Null on a draw and on a battle with no result yet.
victorySize"major" | "minor" | null
How big the win was.
playersBattlePlayer[]
The two players and how they scored.
urlstring
Link to the battle page on milarki.com.

Example response

json
{
  "data": [
    {
      "id": "000b1161c8a864a1f75f",
      "date": "2025-01-14",
      "tournament": "the-behemoth",
      "stage": "swiss",
      "round": 3,
      "scenario": "Lines of Communication",
      "battlePack": "GHB 24/25 4th",
      "battleSize": 2000,
      "winner": "Anders Larsson",
      "victorySize": "major",
      "players": [
        {
          "player": "Anders Larsson",
          "playerId": "L80MTI4R",
          "faction": "Disciples of Tzeentch",
          "subFaction": "Guild of Summoners",
          "outcome": "win",
          "battlePoints": 20,
          "victoryPoints": 28,
          "objectivePoints": 18,
          "battleTacticsScored": 3,
          "drops": 6,
          "role": "defender",
          "metrics": {}
        }
      ],
      "url": "https://www.milarki.com/battles/000b1161c8a864a1f75f"
    }
  ],
  "next": null
}