Skip to content

Tournament detail

GET
/api/tournaments/{id}
curl --request GET \
--url https://foxleague.ai/api/tournaments/1

Returns one tournament with its participants, rounds, matches and standings. A match’s score appears once its broadcast ends. A next-round slot names its team once the match that sends the team there has finished, on air too. Each Swiss round is listed once every match of the round before it has finished. Standings and recent form count finished matches only. The podium appears when the tournament completes.

Who: anyone. With a session:

  • the creator and the invitees of a private tournament read its invite list in whitelist;
  • the creator and the target of a targeted 1v1 challenge read target_user_id;
  • with wallet_address set to your own wallet, the per-viewer fields user_is_participant, user_can_join_private, user_can_join_developer, viewer_blocked_active_1v1 and viewer_blocked_tournament_window are filled.

Refusals:

  • Tournament not found: no tournament has this id.
id
required
integer format: int64

The tournament id.

wallet_address
string

Your own wallet address, the one of your session. It fills the per-viewer fields of the answer. Any other value is ignored, as is the parameter without a session.

Success or a refusal: read success (the refusals are in the description).

Media type application/json
object
code

A machine-readable reason next to error, set only where the caller must act differently. tx_pending: the payment was not refused but could not be verified yet; keep the transaction hash and confirm again with the same hash, never pay twice.

string | null
data

The answer. Present when success is true.

object
matches
required

The matches, by round, then by position. A Swiss round’s matches are listed once every match of the round before it has finished.

Array<object>

One match of a tournament as its schedule and bracket show it.

object
away_badge

Badge of the away team, named by the same rule as away_team_name; null when none.

string | null
away_elo_after

away_elo_at_match plus this match’s rating change (away_elo_after minus away_elo_at_match is the change the match applied; it is not the player’s current rating), present once the match has finished and its rating change applied. Absent otherwise and for an older match whose away_elo_at_match is null.

integer | null format: int32
away_elo_at_match

The away player’s rating for this match, from the moment the match is on air and the away team is named: the player’s current rating until the result is applied after the broadcast, then the rating the match’s change was computed from; null otherwise. null too for a slot with no match (a bye) and for an older match whose rating was not recorded this way: its change is in away_elo_change.

integer | null format: int32
away_elo_change

The away player’s rating change in this match (away_elo_after minus away_elo_at_match, also for an older match that answers neither), present once the match has finished and its rating change applied. Absent otherwise.

integer | null format: int32
away_penalty

A finished match decided on penalties: shootout goals of the away side. null otherwise.

integer | null format: int32
away_score

Goals of the away side once the match’s broadcast ends; null before.

integer | null format: int32
away_seed_place

League + Knockout: the league place drawn into the away seat, by the same rule as home_seed_place.

integer | null format: int32
away_team_name

Away team name, by the same rule as home_team_name.

string | null
bracket_position

Position of the match within its round; null when none.

integer | null format: int32
broadcast_ended_at

When the match’s broadcast ended (RFC 3339); null before.

string | null format: date-time
decided_by

A finished knockout match: regular, extra_time or penalties. null otherwise.

string | null
distribute_tx_hash

Hash of the prize payout transaction of a paid tournament, set when the tournament completes; null before and for a free tournament.

string | null
forfeit_reason

Why a finished match was decided without being played, for example a team could not field a complete squad; null unless is_forfeit is true.

string | null
group_name

A, B and so on for a group match, League for a round robin and for the league phase of League + Knockout, 3rd Place for the third place match; null for knockout and Swiss matches.

string | null
home_badge

Badge of the home team, named by the same rule as home_team_name; null when none.

string | null
home_elo_after

home_elo_at_match plus this match’s rating change (home_elo_after minus home_elo_at_match is the change the match applied; it is not the player’s current rating), present once the match has finished and its rating change applied. Absent otherwise and for an older match whose home_elo_at_match is null.

integer | null format: int32
home_elo_at_match

The home player’s rating for this match, from the moment the match is on air and the home team is named: the player’s current rating until the result is applied after the broadcast, then the rating the match’s change was computed from; null otherwise. null too for a slot with no match (a bye) and for an older match whose rating was not recorded this way: its change is in home_elo_change.

integer | null format: int32
home_elo_change

The home player’s rating change in this match (home_elo_after minus home_elo_at_match, also for an older match that answers neither), present once the match has finished and its rating change applied. Absent otherwise.

integer | null format: int32
home_penalty

A finished match decided on penalties: shootout goals of the home side. null otherwise.

integer | null format: int32
home_score

Goals of the home side once the match’s broadcast ends; null before.

integer | null format: int32
home_seed_place

League + Knockout: the league place drawn into the home seat when the bracket was made (both seats of a play-off match, the top-8 seat of a round of 16 match), for example 24; null on a seat that a tie fills and in every other format.

integer | null format: int32
home_team_name

Home team name. Group, league and first-round matches name it from the start; a later match names it once the match that sends the team here has finished or once this match kicks off. null until then. In a developer tournament, the developer team’s name.

string | null
id
required

The match’s public id: 22 URL-safe characters with no order. Watch the match, read its statistics and download its files by it: GET /api/public/tournament-match/{id}, GET /api/live/tournament-match/{id}, GET /api/replay/tournament-match/{id}, GET /api/public/tournament-match/{id}/stats, GET /api/public/tournament-match/{id}/log. No answer carries the match’s own id.

string
is_bye
required

true for a seed that goes through without an opponent.

boolean
is_forfeit
required

true for a finished match that was decided without being played.

boolean
is_prize_deciding
required

true for the match that settles the prizes: the final and the third place match of a knockout phase; the last match of a round robin or Swiss tournament.

boolean
is_watchable
required

true while the match is on air. After its broadcast, true when its replay can be watched.

boolean
leg

League + Knockout: 1 or 2 for the two matches of a two-legged tie (a tie is one round_number with one bracket_position); null for a single match and in every other format. Each leg carries its own score; the aggregate adds both legs up from the seats (the home team of leg 2 is the away team of leg 1).

integer | null format: int32
round_label

Label of the round, for example Semifinal, Group A - Matchday 2, Matchday 3 or Round 2; null when none.

string | null
round_number
required

Round number, from 1.

integer format: int32
scheduled_at
required

Kickoff (RFC 3339).

string format: date-time
status
required

The match’s state: pending before kickoff, live while it is on air, then its final state once its broadcast ends: forfeit for a match decided without being played and otherwise finished. Read the score only once broadcast_ended_at is set.

string
participants
required

The seated teams by seed.

Array<object>

One seated team of a tournament.

object
badge

Team badge: an IPFS URI or an older inline image; null when the team has none. In a developer tournament: the path of the developer team’s logo; null when it has none.

string | null
dev_team_name

Developer tournament only: the name of the player’s verified developer team. null otherwise.

string | null
elo_rating
required

The player’s current rating.

integer format: int32
formation
required

Formation of the squad the team entered with; 4-4-2 when unknown.

string
id
required

Seat id; standings rows refer to it as participant_id.

integer format: int32
placement

Final place, 1, 2 or 3, set when the tournament completes; null otherwise.

integer | null format: int32
recent_form
required

Up to five latest results, newest first: W, D or L. A tournament match counts once its broadcast ends.

Array<string>
seed

Seed number from the draw at the deadline; may be null before the draw.

integer | null format: int32
squad_ovr
required

Average rating of the squad the team entered with, as a whole number. 0 for a developer team.

integer format: int32
team_name
required

The team name; Team #<user_id> when the player has no team.

string
user_id
required

User id of the player.

integer format: int32
wallet_address
required

Wallet of the player.

string
rounds
required

The rounds, by round number. A Swiss round is listed once every match of the round before it has finished.

Array<object>

One round of a tournament.

object
round_label

Label of the round, for example Semifinal, Group A - Matchday 2, Matchday 3 or Round 2; null when none.

string | null
round_number
required

Round number, from 1.

integer format: int32
round_type
required

group (group stage or round robin), knockout or swiss.

string
scheduled_at
required

Scheduled time of the round (RFC 3339).

string format: date-time
status
required

pending until the broadcast of every match of the round has ended, then finished.

string
tournament_id
required

The tournament id.

integer format: int64
standings

The group, league or Swiss table from finished matches, as GET /api/tournaments/{id}/standings answers it. null for a knockout tournament.

Array<object> | null

One team’s row in a group, league or Swiss table.

object
drawn
required

Matches drawn.

integer format: int32
goals_against
required

Goals conceded.

integer format: int32
goals_for
required

Goals scored.

integer format: int32
group_name

A, B and so on for a group, League for a round robin; null for a Swiss tournament.

string | null
id
required

Id of the row.

integer format: int32
lost
required

Matches lost.

integer format: int32
participant_id
required

Seat id of the team: the id of its row in participants.

integer format: int32
played
required

Finished matches played.

integer format: int32
points
required

Points: 3 for a win, 1 for a draw, minus 1 for each match neither team could play.

integer format: int32
tournament_id
required

The tournament id.

integer format: int64
won
required

Matches won.

integer format: int32
tournament
required

The tournament.

object
away_penalty

Completed 1v1 challenge rows decided on penalties: shootout goals of the away side. Absent otherwise.

integer | null format: int32
away_score

Completed 1v1 challenge rows of the tournament lists: goals of the away side. Absent otherwise.

integer | null format: int32
blocking_window_end

End of that reserved window (RFC 3339): one hour after the tournament’s booked play time, about 3 minutes per match without the time between games; null when there is none. This is not when the tournament ends: it can keep playing after its window for hours or days.

string | null format: date-time
blocking_window_start

Start of the time window a standard tournament reserves on the schedule, one hour before kickoff (RFC 3339). No other tournament may reserve an overlapping window. null for 1v1 challenges and developer tournaments.

string | null format: date-time
cancelled_at

When the tournament was cancelled (RFC 3339); null when it was not.

string | null format: date-time
challenge_deadline_minutes

1v1 challenge: the minutes it was opened for. null for a standard tournament.

integer | null format: int32
completed_at

When the tournament completed (RFC 3339); null before.

string | null format: date-time
created_at
required

When the tournament was created (RFC 3339).

string format: date-time
creator_badge

1v1 challenge rows of the tournament lists: the creator’s team badge. Absent otherwise.

string | null
creator_team_name

1v1 challenge rows of the tournament lists: the creator’s team name. Absent otherwise.

string | null
creator_user_id
required

User id of the creator (the organizer).

integer format: int32
deadline
required

Registration closes at this time (RFC 3339).

string format: date-time
decided_by

Completed 1v1 challenge rows of the tournament lists: regular, extra_time or penalties. Absent otherwise.

string | null
description

Text written by the creator; null when none.

string | null
developer_mode

true when only teams with a verified developer binary may join.

boolean | null
distribute_tx_hash

Completed 1v1 challenge rows of the tournament lists: hash of the prize payout transaction. Absent otherwise.

string | null
entry_fee_foxsy
required

Entry fee in whole FOXSY; 0 for Bronze.

integer format: int64
featured
required

true for a tournament the game features: it is listed first and enters the hall of fame when it completes.

boolean
format
required

knockout, groups_knockout, round_robin, swiss or league_knockout (League + Knockout: 36 teams in one league table drawn from four pots).

string
has_third_place_match
required

true when a match for third place is played.

boolean
home_and_away

true for a round robin where every pair of teams meets twice.

boolean | null
home_penalty

Completed 1v1 challenge rows decided on penalties: shootout goals of the home side. Absent otherwise.

integer | null format: int32
home_score

Completed 1v1 challenge rows of the tournament lists: goals of the home side. Absent otherwise.

integer | null format: int32
home_user_id

Completed 1v1 challenge rows of GET /api/tournaments: user id of the home side, to match the score to the teams (the creator is not always at home). Absent otherwise.

integer | null format: int32
id
required

The tournament id.

integer format: int64
is_private

true when only invited teams may join.

boolean
max_teams
required

Seats. 2 for a 1v1 challenge.

integer format: int32
min_teams
required

Teams needed to start; with fewer at the deadline the tournament is cancelled.

integer format: int32
opponent_badge

1v1 challenge rows of the tournament lists: the opponent’s team badge once an opponent holds the second seat. Absent otherwise.

string | null
opponent_team_name

1v1 challenge rows of the tournament lists: the opponent’s team name once an opponent holds the second seat. Absent otherwise.

string | null
organizer_only

Tournament detail only: true when the creator runs the tournament without a seat. Absent elsewhere.

boolean | null
participant_count

Seats taken. Filled by GET /api/tournaments; null in other answers.

integer | null format: int64
round_interval_minutes
required

Minutes between one match’s kickoff and the next.

integer format: int32
runner_up_user_id

User id of the runner-up, set when the tournament completes; null before.

integer | null format: int32
sc_tournament_id

Id of the tournament on chain (equal to id) for a paid tournament once it is created there; null for a free tournament.

integer | null format: int64
started_at

When registration closed and the draw was made (RFC 3339); null before.

string | null format: date-time
starts_at
required

Kickoff of the first match (RFC 3339).

string format: date-time
status
required

open: registration is open. pending_sc: a paid tournament is being created on chain and cannot be joined yet. active: registration closed and the tournament is under way. completed: finished, podium set. cancelled: too few teams at the deadline or cancelled by its creator.

string
target_user_id

Targeted 1v1 challenge: user id of the only opponent who may accept. Given to the creator and the target only; null for everyone else and for any other tournament.

integer | null format: int32
targeted

true for a 1v1 challenge locked to one opponent. Absent otherwise.

boolean
targeted_to_you

true when you are the opponent a targeted 1v1 challenge is locked to. Absent otherwise.

boolean
third_place_user_id

User id of the third-placed team, set when the tournament completes; null before and when no third place is decided.

integer | null format: int32
tier
required

bronze (free), silver or gold (paid in FOXSY).

string
title
required

Name of the tournament.

string
winner_user_id

User id of the winner, set when the tournament completes; null before.

integer | null format: int32
user_can_join_developer

With wallet_address: true for a normal tournament; for a developer tournament, true when you have a verified developer binary. null without wallet_address.

boolean | null
user_can_join_private

With wallet_address: true for a public tournament; for a private one, true when you are invited or are the creator (not an organizer-only creator). null without wallet_address.

boolean | null
user_is_participant

With wallet_address: true when you hold a seat. null without wallet_address.

boolean | null
viewer_blocked_active_1v1

1v1 challenge with wallet_address: true when you already have another open or running 1v1 challenge, so a join would be refused. null otherwise.

boolean | null
viewer_blocked_tournament_window

1v1 challenge with wallet_address: true when a join would be refused: from an hour before a tournament or challenge match of yours until its result is out; from an hour before your group’s last kickoff until the group’s results are out; from an hour before your Swiss round match until all the round’s results are out. false when you already hold a seat in this challenge. null otherwise.

boolean | null
whitelist

The teams invited to a private tournament, given to its creator and its invitees. An empty list for everyone else and for a public tournament.

Array<object>

One team invited to a private tournament.

object
badge

The invited team’s badge: an IPFS URI or an older inline image; null when none.

string | null
team_name

The invited player’s team name; null when the player has no team.

string | null
user_id
required

User id of the invited player.

integer format: int32
error

Why the request was refused, in plain words. Present when success is false.

string | null
success
required

true when the request did what it asked. false is a refusal: read error.

boolean
Example
{
"data": {
"matches": [
{
"away_badge": "ipfs://bafkreim6p4g37ztnovmizwdiaeq3kdfyspsc5lkr4aqxvupctnw",
"away_elo_after": 1288,
"away_elo_at_match": 1302,
"away_elo_change": -14,
"away_penalty": null,
"away_score": 1,
"away_seed_place": null,
"away_team_name": "North Gate",
"bracket_position": 0,
"broadcast_ended_at": "2026-10-02T17:09:12Z",
"decided_by": "regular",
"distribute_tx_hash": null,
"forfeit_reason": null,
"group_name": null,
"home_badge": "ipfs://bafkreij7ufrdl3erbfqfoeqh5av2ricphkqdlmttns4lrwbqcab",
"home_elo_after": 1284,
"home_elo_at_match": 1270,
"home_elo_change": 14,
"home_penalty": null,
"home_score": 2,
"home_seed_place": null,
"home_team_name": "Harbor Foxes",
"id": "b8HcT0vW3qLs-Jm6Nd2yUe",
"is_bye": false,
"is_forfeit": false,
"is_prize_deciding": false,
"is_watchable": true,
"leg": null,
"round_label": "Semifinal",
"round_number": 1,
"scheduled_at": "2026-10-02T17:00:00Z",
"status": "finished"
},
{
"away_badge": "ipfs://bafkrei7qa5efe6qeqpno57ye6scmejvqtia6d7rgn7ss555hmtf",
"away_elo_at_match": null,
"away_penalty": null,
"away_score": null,
"away_seed_place": null,
"away_team_name": "Copper Valley",
"bracket_position": 1,
"broadcast_ended_at": null,
"decided_by": null,
"distribute_tx_hash": null,
"forfeit_reason": null,
"group_name": null,
"home_badge": "ipfs://bafkreilavyf6rmpafqfjzczbttofjyu7jsjc3ibofbcixgy4dbp",
"home_elo_at_match": null,
"home_penalty": null,
"home_score": null,
"home_seed_place": null,
"home_team_name": "Ember Town",
"id": "Lp5zXa9_Gf1Kr7Qw2Ve8Tm",
"is_bye": false,
"is_forfeit": false,
"is_prize_deciding": false,
"is_watchable": false,
"leg": null,
"round_label": "Semifinal",
"round_number": 1,
"scheduled_at": "2026-10-02T17:30:00Z",
"status": "pending"
},
{
"away_badge": null,
"away_elo_at_match": null,
"away_penalty": null,
"away_score": null,
"away_seed_place": null,
"away_team_name": null,
"bracket_position": 0,
"broadcast_ended_at": null,
"decided_by": null,
"distribute_tx_hash": null,
"forfeit_reason": null,
"group_name": null,
"home_badge": "ipfs://bafkreij7ufrdl3erbfqfoeqh5av2ricphkqdlmttns4lrwbqcab",
"home_elo_at_match": null,
"home_penalty": null,
"home_score": null,
"home_seed_place": null,
"home_team_name": "Harbor Foxes",
"id": "Zt3Mn6Bq-Hy0Wc8Ja4Ls1d",
"is_bye": false,
"is_forfeit": false,
"is_prize_deciding": true,
"is_watchable": false,
"leg": null,
"round_label": "Final",
"round_number": 2,
"scheduled_at": "2026-10-02T18:00:00Z",
"status": "pending"
}
],
"participants": [
{
"badge": "ipfs://bafkreij7ufrdl3erbfqfoeqh5av2ricphkqdlmttns4lrwbqcab",
"dev_team_name": null,
"elo_rating": 1284,
"formation": "4-3-3",
"id": 2201,
"placement": null,
"recent_form": [
"W",
"W",
"D",
"L",
"W"
],
"seed": 1,
"squad_ovr": 61,
"team_name": "Harbor Foxes",
"user_id": 57,
"wallet_address": "erd15feryxhrdz9m6y09mr8wrerwzgj6f8ntxvhxyrdlm5aahn0t09nl4ujy86"
},
{
"badge": "ipfs://bafkreim6p4g37ztnovmizwdiaeq3kdfyspsc5lkr4aqxvupctnw",
"dev_team_name": null,
"elo_rating": 1288,
"formation": "4-4-2",
"id": 2202,
"placement": null,
"recent_form": [
"L",
"W",
"W",
"W",
"D"
],
"seed": 2,
"squad_ovr": 63,
"team_name": "North Gate",
"user_id": 61,
"wallet_address": "erd124fl6zy54klay937yrnujckpak28lrdjg0eel92ue3gm36kcwf9tfwwqlt"
},
{
"badge": "ipfs://bafkreilavyf6rmpafqfjzczbttofjyu7jsjc3ibofbcixgy4dbp",
"dev_team_name": null,
"elo_rating": 1190,
"formation": "4-3-3",
"id": 2203,
"placement": null,
"recent_form": [
"D",
"L",
"W"
],
"seed": 3,
"squad_ovr": 58,
"team_name": "Ember Town",
"user_id": 73,
"wallet_address": "erd1sjqf6h5graeeeex7ervydu284rxqfxhpydcfskh788la77n9fx4s72pdhf"
},
{
"badge": "ipfs://bafkrei7qa5efe6qeqpno57ye6scmejvqtia6d7rgn7ss555hmtf",
"dev_team_name": null,
"elo_rating": 1225,
"formation": "3-5-2",
"id": 2204,
"placement": null,
"recent_form": [
"W",
"L",
"L",
"W",
"W"
],
"seed": 4,
"squad_ovr": 60,
"team_name": "Copper Valley",
"user_id": 88,
"wallet_address": "erd1pn9sh2kw4wv0ewvlkpp37svkukh9wxw7v4d7q7k98cv7tm49eae922gpfa"
}
],
"rounds": [
{
"round_label": "Semifinal",
"round_number": 1,
"round_type": "knockout",
"scheduled_at": "2026-10-02T17:00:00Z",
"status": "pending",
"tournament_id": 398
},
{
"round_label": "Final",
"round_number": 2,
"round_type": "knockout",
"scheduled_at": "2026-10-02T18:00:00Z",
"status": "pending",
"tournament_id": 398
}
],
"standings": null,
"tournament": {
"blocking_window_end": "2026-10-02T18:12:00Z",
"blocking_window_start": "2026-10-02T16:00:00Z",
"cancelled_at": null,
"challenge_deadline_minutes": null,
"completed_at": null,
"created_at": "2026-09-29T08:03:11Z",
"creator_user_id": 73,
"deadline": "2026-10-02T16:00:00Z",
"description": null,
"developer_mode": false,
"entry_fee_foxsy": 5000,
"featured": true,
"format": "knockout",
"has_third_place_match": false,
"home_and_away": false,
"id": 398,
"is_private": false,
"max_teams": 4,
"min_teams": 4,
"organizer_only": false,
"participant_count": null,
"round_interval_minutes": 30,
"runner_up_user_id": null,
"sc_tournament_id": 398,
"started_at": "2026-10-02T16:00:41Z",
"starts_at": "2026-10-02T17:00:00Z",
"status": "active",
"target_user_id": null,
"third_place_user_id": null,
"tier": "gold",
"title": "Autumn Knockout",
"winner_user_id": null
},
"user_can_join_developer": null,
"user_can_join_private": null,
"user_is_participant": null,
"viewer_blocked_active_1v1": null,
"viewer_blocked_tournament_window": null,
"whitelist": []
},
"success": true
}

No valid session. The body is plain text: Missing Authorization header, Invalid Authorization format, Invalid session token or Session expired or invalid. Sign in again.

Media type text/plain
string
Example
Session expired or invalid