{
  "openapi": "3.0.3",
  "info": {
    "title": "TopDeck.gg API",
    "description": "Access tournament data from TopDeck.gg — players, standings, decklists, matchups, and more. Free to use with attribution required.\n\nAny project using this API must include a visible credit and link back to [TopDeck.gg](https://topdeck.gg).",
    "version": "2.0.0",
    "contact": {
      "name": "TopDeck.gg Support",
      "email": "contact@topdeck.gg",
      "url": "https://topdeck.gg"
    },
    "termsOfService": "https://topdeck.gg/api/docs"
  },
  "servers": [
    {
      "url": "https://topdeck.gg/api",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/v2/tournaments": {
      "post": {
        "operationId": "searchTournaments",
        "summary": "Bulk Tournaments",
        "description": "Search and retrieve information about completed tournaments — players, standings, decklists, matchups, and more. Supports two modes: query-based filtering (game, format, date range) or direct TID lookup.\n\nRate limit: lower than default (heavy endpoint).",
        "tags": ["Tournaments"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkTournamentRequest"
              },
              "examples": {
                "queryMode": {
                  "summary": "Filter by game, format, and date range",
                  "value": {
                    "game": "Magic: The Gathering",
                    "format": "EDH",
                    "last": 30,
                    "columns": ["name", "decklist", "wins", "draws", "losses"],
                    "rounds": true
                  }
                },
                "tidMode": {
                  "summary": "Fetch specific tournaments by ID",
                  "value": {
                    "TID": ["abc123", "def456"],
                    "columns": ["name", "decklist", "wins", "losses"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Array of tournament objects with standings and optional round data.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/BulkTournament"
                  }
                },
                "example": [
                  {
                    "TID": "abc123",
                    "tournamentName": "Weekly EDH",
                    "swissNum": 5,
                    "startDate": 1627844461,
                    "game": "Magic: The Gathering",
                    "format": "EDH",
                    "topCut": 8,
                    "eventData": {
                      "city": "New York",
                      "state": "NY",
                      "location": "Local Game Store"
                    },
                    "standings": [
                      {
                        "name": "Player Name",
                        "decklist": "~~Commanders~~\n...",
                        "wins": 4,
                        "draws": 1,
                        "losses": 0
                      }
                    ],
                    "rounds": [
                      {
                        "round": 1,
                        "tables": []
                      }
                    ]
                  }
                ]
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/v2/my-tournaments": {
      "get": {
        "operationId": "getMyTournaments",
        "summary": "My Tournaments",
        "description": "Returns all tournaments owned by the authenticated API key holder. By default, only upcoming tournaments are returned.\n\nRequires a TopDeck subscription and at least one tournament created on your account.",
        "tags": ["Tournaments"],
        "parameters": [
          {
            "name": "filter",
            "in": "query",
            "description": "Set to `all` to include past tournaments. Default returns only upcoming.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["upcoming", "all"],
              "default": "upcoming"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Array of tournaments owned by the API key holder.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MyTournament"
                  }
                },
                "example": [
                  {
                    "tid": "abc123",
                    "name": "Weekly Modern",
                    "game": "Magic: The Gathering",
                    "format": "Modern",
                    "startDate": 1627844461,
                    "endDate": 1627855261,
                    "status": "Not Started",
                    "location": {
                      "name": "Card Kingdom Seattle",
                      "city": "Seattle",
                      "state": "WA",
                      "country": "US"
                    },
                    "headerImage": "https://..."
                  }
                ]
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/v2/tournaments/{TID}": {
      "get": {
        "operationId": "getTournament",
        "summary": "Single Tournament",
        "description": "Retrieve detailed information about a specific tournament — info, standings, and all rounds in a single response.\n\nConditional fields:\n- **Decklists**: Only when tournament has ended OR organizer enabled \"Show Decks\"\n- **deckObj**: Only when structured deck data is available\n- **Discord fields**: Only when tournament includes Discord info\n- **Win rate fields**: League tournaments use \"successRate\" instead of \"winRate\"",
        "tags": ["Tournaments"],
        "parameters": [
          {
            "$ref": "#/components/parameters/TID"
          }
        ],
        "responses": {
          "200": {
            "description": "Full tournament object with info, standings, and rounds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FullTournament"
                },
                "example": {
                  "data": {
                    "name": "Tournament Name",
                    "game": "Magic: The Gathering",
                    "format": "EDH",
                    "startDate": 1627844461
                  },
                  "standings": [
                    {
                      "standing": 1,
                      "name": "Player Name",
                      "id": "abc123",
                      "points": 15,
                      "winRate": 0.8,
                      "opponentWinRate": 0.6
                    }
                  ],
                  "rounds": [
                    {
                      "round": 1,
                      "tables": []
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/v2/tournaments/{TID}/info": {
      "get": {
        "operationId": "getTournamentInfo",
        "summary": "Tournament Info",
        "description": "Retrieve basic tournament information including location and scheduling details.",
        "tags": ["Tournaments"],
        "parameters": [
          {
            "$ref": "#/components/parameters/TID"
          }
        ],
        "responses": {
          "200": {
            "description": "Tournament metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TournamentInfo"
                },
                "example": {
                  "tid": "abc123",
                  "name": "Tournament Name",
                  "game": "Magic: The Gathering",
                  "format": "EDH",
                  "startDate": 1627844461,
                  "endDate": 1627855261,
                  "status": "Complete",
                  "location": {
                    "name": "Card Kingdom Seattle",
                    "city": "Seattle",
                    "state": "WA",
                    "country": "US"
                  },
                  "headerImage": "https://..."
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/v2/tournaments/{TID}/standings": {
      "get": {
        "operationId": "getTournamentStandings",
        "summary": "Standings",
        "description": "Retrieve standings for a specific tournament.\n\nConditional fields:\n- **Decklists**: Only when tournament has ended OR organizer enabled \"Show Decks\"\n- **deckObj**: Only when structured deck data is available\n- **Discord fields**: Only when tournament includes Discord info\n- **Win rate fields**: League tournaments use `successRate` / `opponentSuccessRate`\n- **Game win rates**: Only in Pairs mode tournaments (`gameWinRate`, `opponentGameWinRate`)",
        "tags": ["Tournaments"],
        "parameters": [
          {
            "$ref": "#/components/parameters/TID"
          }
        ],
        "responses": {
          "200": {
            "description": "Array of player standings. Schema varies by tournament type (standard, league, pairs).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Standing"
                  }
                },
                "examples": {
                  "standard": {
                    "summary": "Standard Tournament",
                    "value": [
                      {
                        "standing": 1,
                        "name": "Player Name",
                        "id": "abc123",
                        "decklist": "~~Commanders~~\n...",
                        "deckObj": {},
                        "points": 15,
                        "winRate": 0.83,
                        "opponentWinRate": 0.7
                      }
                    ]
                  },
                  "league": {
                    "summary": "League Tournament",
                    "value": [
                      {
                        "standing": 1,
                        "name": "Player Name",
                        "id": "abc123",
                        "points": 15,
                        "successRate": 0.83,
                        "opponentSuccessRate": 0.7
                      }
                    ]
                  },
                  "pairs": {
                    "summary": "Pairs Mode",
                    "value": [
                      {
                        "standing": 1,
                        "name": "Player Name",
                        "id": "abc123",
                        "points": 15,
                        "winRate": 0.83,
                        "opponentWinRate": 0.7,
                        "gameWinRate": 0.75,
                        "opponentGameWinRate": 0.65
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/v2/tournaments/{TID}/players/{ID}": {
      "get": {
        "operationId": "getPlayer",
        "summary": "Player Details",
        "description": "Retrieve detailed information about a specific player in a tournament.\n\nConditional fields:\n- **Decklists**: Only when tournament has ended OR organizer enabled \"Show Decks\"\n- **deckObj**: Only when structured deck data is available\n- **Decklist format**: Can be either a URL or text string",
        "tags": ["Tournaments"],
        "parameters": [
          {
            "$ref": "#/components/parameters/TID"
          },
          {
            "name": "ID",
            "in": "path",
            "required": true,
            "description": "Player's unique identifier within the tournament.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Player details including standings, decklist, and match record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlayerDetail"
                },
                "example": {
                  "name": "Player Name",
                  "standing": 1,
                  "decklist": "~~Commanders~~\n...",
                  "deckObj": {
                    "Commanders": {},
                    "Mainboard": {}
                  },
                  "winRate": 0.83,
                  "gamesPlayed": 10,
                  "gamesWon": 8,
                  "byes": 0,
                  "gamesDrawn": 1,
                  "gamesLost": 1
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/v2/tournaments/{TID}/rounds": {
      "get": {
        "operationId": "getTournamentRounds",
        "summary": "All Rounds",
        "description": "Retrieve all rounds of a specific tournament.\n\nConditional fields:\n- **Decklists**: Only when tournament has ended OR organizer enabled \"Show Decks\"\n- **deckObj**: Only when structured deck data is available\n- **Discord fields**: Only when tournament includes Discord info",
        "tags": ["Tournaments"],
        "parameters": [
          {
            "$ref": "#/components/parameters/TID"
          }
        ],
        "responses": {
          "200": {
            "description": "Array of round objects, each containing tables with player matchups.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Round"
                  }
                },
                "example": [
                  {
                    "round": 1,
                    "tables": [
                      {
                        "table": 1,
                        "players": [
                          { "name": "Player 1", "id": "abc" },
                          { "name": "Player 2", "id": "def" }
                        ],
                        "winner": "Player 1",
                        "winner_id": "abc",
                        "status": "Completed"
                      }
                    ]
                  },
                  {
                    "round": "Top 8",
                    "tables": []
                  }
                ]
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/v2/tournaments/{TID}/rounds/latest": {
      "get": {
        "operationId": "getLatestRound",
        "summary": "Latest Round",
        "description": "Retrieve the current/latest round of a specific tournament. Returns the same table structure as the rounds endpoint, but only for the most recent round.\n\nConditional fields:\n- **Decklists**: Only when tournament has ended OR organizer enabled \"Show Decks\"\n- **deckObj**: Only when structured deck data is available\n- **Discord fields**: Only when tournament includes Discord info",
        "tags": ["Tournaments"],
        "parameters": [
          {
            "$ref": "#/components/parameters/TID"
          }
        ],
        "responses": {
          "200": {
            "description": "Array of table objects for the latest round.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Table"
                  }
                },
                "example": [
                  {
                    "table": 1,
                    "players": [
                      { "name": "Player 1", "id": "abc" },
                      { "name": "Player 2", "id": "def" }
                    ],
                    "winner": "Player 1",
                    "winner_id": "abc",
                    "status": "Completed"
                  },
                  {
                    "table": "Byes",
                    "players": [
                      { "name": "Player 5", "id": "ghi" }
                    ],
                    "status": "Bye"
                  }
                ]
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/v2/tournaments/{TID}/attendees": {
      "get": {
        "operationId": "getTournamentAttendees",
        "summary": "Attendees",
        "description": "Retrieve all attendees for a tournament — registered players, dropped players, and waitlisted users.\n\n**Staff only**: This endpoint requires tournament staff permissions. Unauthorized users receive a 403.",
        "tags": ["Tournaments"],
        "parameters": [
          {
            "$ref": "#/components/parameters/TID"
          }
        ],
        "responses": {
          "200": {
            "description": "Array of attendee objects including players, dropped players, and waitlisted users.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Attendee"
                  }
                },
                "example": [
                  {
                    "uid": "player123",
                    "name": "John Doe",
                    "email": "john@example.com",
                    "status": "player",
                    "standing": 1,
                    "decklist": "...",
                    "deckObj": {}
                  },
                  {
                    "uid": "waitlist789",
                    "name": "Bob Wilson",
                    "status": "waitlist",
                    "waitlistStatus": "waiting",
                    "waitlistPosition": 1
                  }
                ]
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": {
            "description": "Insufficient permissions. Requires tournament staff access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Forbidden: Insufficient permissions"
                }
              }
            }
          },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Your TopDeck.gg API key. Get one free at https://topdeck.gg/account"
      }
    },
    "parameters": {
      "TID": {
        "name": "TID",
        "in": "path",
        "required": true,
        "description": "Tournament identifier.",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "BulkTournamentRequest": {
        "type": "object",
        "description": "Request body for bulk tournament search. Use either TID mode (specific IDs) or query mode (game/format/date filters).",
        "properties": {
          "TID": {
            "oneOf": [
              { "type": "string" },
              { "type": "array", "items": { "type": "string" } }
            ],
            "description": "Tournament ID or array of IDs. When provided, game/format/date filters are ignored."
          },
          "game": {
            "type": "string",
            "description": "Game name for filtering. Case sensitive. Example: \"Magic: The Gathering\", \"Pokemon\", \"Yu-Gi-Oh!\""
          },
          "format": {
            "type": "string",
            "description": "Game format for filtering. Case sensitive. Example: \"Standard\", \"EDH\", \"Modern\""
          },
          "start": {
            "type": "integer",
            "description": "Unix timestamp (seconds) — earliest tournament start date."
          },
          "end": {
            "type": "integer",
            "description": "Unix timestamp (seconds) — latest tournament end date."
          },
          "last": {
            "type": "integer",
            "description": "Number of days back from today to include. Alternative to start/end."
          },
          "participantMin": {
            "type": "integer",
            "description": "Minimum number of participants."
          },
          "participantMax": {
            "type": "integer",
            "description": "Maximum number of participants."
          },
          "columns": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["name", "decklist", "wins", "winsSwiss", "winsBracket", "winRate", "winRateSwiss", "winRateBracket", "byes", "draws", "losses", "lossesSwiss", "lossesBracket", "id"]
            },
            "default": ["decklist", "wins", "draws", "losses"],
            "description": "Player columns to include in standings."
          },
          "rounds": {
            "oneOf": [
              { "type": "boolean" },
              { "type": "array", "items": { "type": "string" } }
            ],
            "default": false,
            "description": "Round details to include. `true` returns [\"round\", \"tables\"]. Array for custom fields."
          },
          "tables": {
            "type": "array",
            "items": { "type": "string" },
            "default": ["table", "players", "winner", "status"],
            "description": "Table details to include within rounds."
          },
          "players": {
            "type": "array",
            "items": { "type": "string" },
            "default": ["name", "id"],
            "description": "Player details within round tables."
          }
        }
      },
      "BulkTournament": {
        "type": "object",
        "properties": {
          "TID": {
            "type": "string",
            "description": "Tournament identifier."
          },
          "tournamentName": {
            "type": "string",
            "description": "Name of the tournament."
          },
          "swissNum": {
            "type": "number",
            "description": "Number of Swiss rounds played."
          },
          "startDate": {
            "type": "number",
            "description": "Unix timestamp of tournament start."
          },
          "game": {
            "type": "string",
            "description": "Game being played."
          },
          "format": {
            "type": "string",
            "description": "Game format."
          },
          "topCut": {
            "type": "number",
            "description": "Size of the top cut bracket (0 if none)."
          },
          "eventData": {
            "$ref": "#/components/schemas/EventData"
          },
          "standings": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Player standing. Fields depend on the `columns` request parameter."
            },
            "description": "Player standings based on requested columns."
          },
          "rounds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Round"
            },
            "description": "Round data. Only included when `rounds` parameter is set."
          }
        }
      },
      "MyTournament": {
        "type": "object",
        "properties": {
          "tid": {
            "type": "string",
            "description": "Tournament ID."
          },
          "name": {
            "type": "string",
            "description": "Tournament name."
          },
          "game": {
            "type": "string",
            "description": "Game being played."
          },
          "format": {
            "type": "string",
            "description": "Game format."
          },
          "startDate": {
            "type": "number",
            "description": "Unix timestamp of start."
          },
          "endDate": {
            "type": ["number", "null"],
            "description": "Unix timestamp of end."
          },
          "status": {
            "type": "string",
            "enum": ["Complete", "Ongoing", "Not Started"],
            "description": "Tournament status."
          },
          "location": {
            "oneOf": [
              { "$ref": "#/components/schemas/Location" },
              { "type": "null" }
            ],
            "description": "Location details."
          },
          "headerImage": {
            "type": ["string", "null"],
            "description": "URL of event header image."
          }
        }
      },
      "FullTournament": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "name": { "type": "string" },
              "game": { "type": "string" },
              "format": { "type": "string" },
              "startDate": { "type": "number" }
            },
            "description": "Tournament metadata."
          },
          "standings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Standing"
            },
            "description": "Player standings with detailed stats."
          },
          "rounds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Round"
            },
            "description": "All rounds with table details."
          }
        }
      },
      "TournamentInfo": {
        "type": "object",
        "properties": {
          "tid": { "type": "string", "description": "Tournament ID." },
          "name": { "type": "string", "description": "Tournament name." },
          "game": { "type": "string", "description": "Game being played." },
          "format": { "type": "string", "description": "Game format." },
          "startDate": { "type": "number", "description": "Unix timestamp of start." },
          "endDate": { "type": ["number", "null"], "description": "Unix timestamp of end." },
          "status": {
            "type": "string",
            "enum": ["Complete", "Ongoing", "Not Started"],
            "description": "Tournament status."
          },
          "location": {
            "oneOf": [
              { "$ref": "#/components/schemas/Location" },
              { "type": "null" }
            ],
            "description": "Location details."
          },
          "headerImage": { "type": ["string", "null"], "description": "URL of event header image." }
        }
      },
      "Standing": {
        "type": "object",
        "properties": {
          "standing": { "type": "number", "description": "Player's standing position." },
          "name": { "type": "string", "description": "Player's display name." },
          "id": { "type": "string", "description": "Player's unique identifier." },
          "decklist": { "type": "string", "description": "Decklist as text or URL. Conditional." },
          "deckObj": { "type": "object", "description": "Structured deck data. Conditional." },
          "points": { "type": "number", "description": "Total match points." },
          "winRate": { "type": "number", "description": "Match win rate (0.0–1.0). Standard tournaments." },
          "opponentWinRate": { "type": "number", "description": "Opponent match win rate. Standard tournaments." },
          "successRate": { "type": "number", "description": "Success rate (0.0–1.0). League tournaments only." },
          "opponentSuccessRate": { "type": "number", "description": "Opponent success rate. League tournaments only." },
          "gameWinRate": { "type": "number", "description": "Game win rate. Pairs mode only." },
          "opponentGameWinRate": { "type": "number", "description": "Opponent game win rate. Pairs mode only." }
        }
      },
      "PlayerDetail": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "description": "Player's display name." },
          "standing": { "type": "number", "description": "Current tournament standing." },
          "decklist": { "type": "string", "description": "Decklist as text or URL. Conditional." },
          "deckObj": { "type": "object", "description": "Structured deck data. Conditional." },
          "winRate": { "type": "number", "description": "Overall win rate (0.0–1.0)." },
          "gamesPlayed": { "type": "number", "description": "Total games played." },
          "gamesWon": { "type": "number", "description": "Total games won." },
          "byes": { "type": "number", "description": "Byes received." },
          "gamesDrawn": { "type": "number", "description": "Total draws." },
          "gamesLost": { "type": "number", "description": "Total losses." }
        }
      },
      "Round": {
        "type": "object",
        "properties": {
          "round": {
            "oneOf": [
              { "type": "number" },
              { "type": "string" }
            ],
            "description": "Round number or bracket label (e.g. \"Top 8\")."
          },
          "tables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Table"
            }
          }
        }
      },
      "Table": {
        "type": "object",
        "properties": {
          "table": {
            "oneOf": [
              { "type": "number" },
              { "type": "string" }
            ],
            "description": "Table number or \"Byes\" for bye assignments."
          },
          "players": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": { "type": "string" },
                "id": { "type": "string" }
              }
            }
          },
          "winner": {
            "type": ["string", "null"],
            "description": "Winner's name. Null for draws or unfinished."
          },
          "winner_id": {
            "type": ["string", "null"],
            "description": "Winner's ID, \"Draw\" for ties, null for unfinished."
          },
          "status": {
            "type": "string",
            "enum": ["Completed", "Active", "Pending", "Bye"],
            "description": "Match status."
          }
        }
      },
      "EventData": {
        "type": "object",
        "properties": {
          "lat": { "type": "number", "description": "Latitude." },
          "lng": { "type": "number", "description": "Longitude." },
          "city": { "type": "string", "description": "City name." },
          "state": { "type": "string", "description": "State/province." },
          "location": { "type": "string", "description": "Venue name." },
          "headerImage": { "type": "string", "description": "Event header image URL." }
        }
      },
      "Location": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "description": "Venue name." },
          "city": { "type": "string", "description": "City." },
          "state": { "type": "string", "description": "State/province." },
          "country": { "type": "string", "description": "Country code." },
          "lat": { "type": "number", "description": "Latitude." },
          "lng": { "type": "number", "description": "Longitude." }
        }
      },
      "Attendee": {
        "type": "object",
        "properties": {
          "uid": { "type": ["string", "null"], "description": "User's unique identifier." },
          "name": { "type": "string", "description": "Display name." },
          "email": { "type": ["string", "null"], "description": "Email address." },
          "discord": { "type": ["string", "null"], "description": "Discord username." },
          "status": {
            "type": "string",
            "enum": ["player", "dropped", "waitlist"],
            "description": "Attendee status."
          },
          "standing": { "type": ["number", "null"], "description": "Tournament standing. Null for dropped/waitlist." },
          "decklist": { "type": ["string", "null"], "description": "Decklist URL if available." },
          "deckObj": { "type": ["object", "null"], "description": "Structured deck data." },
          "joinedAt": { "type": ["number", "null"], "description": "Unix timestamp when user joined waitlist. Waitlist only." },
          "waitlistStatus": {
            "type": "string",
            "enum": ["waiting", "offered", "accepted", "declined", "expired", "moved"],
            "description": "Waitlist sub-status. Waitlist only."
          },
          "waitlistPosition": { "type": ["number", "null"], "description": "Position in queue. Only for \"waiting\" status." },
          "offeredAt": { "type": ["number", "null"], "description": "When spot was offered. Waitlist only." },
          "expirationTimestamp": { "type": ["number", "null"], "description": "When offer expires. Waitlist only." }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer",
            "description": "HTTP status code."
          },
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Missing or invalid parameters.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": {
              "status": 400,
              "error": "Both \"game\" and \"format\" fields are required."
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Invalid or missing API key.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": {
              "status": 401,
              "error": "INVALID API KEY!"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests per minute.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": {
              "status": 429,
              "error": "Rate limit Exceeded"
            }
          }
        }
      },
      "ServerError": {
        "description": "Internal server error.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" },
            "example": {
              "status": 500,
              "error": "Internal Server Error"
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Tournaments",
      "description": "Endpoints for accessing tournament data — search, standings, rounds, players, and attendees."
    }
  ]
}