{
  "openapi": "3.1.0",
  "info": {
    "title": "SWU Meta Stats API",
    "description": "Public read-only REST API for Star Wars: Unlimited competitive tournament data. Includes archetypes, matchups, decklists, cards, tier lists, and player statistics. All endpoints return JSON and require no authentication.",
    "version": "1.0.0",
    "contact": {
      "email": "swumetastats@gmail.com",
      "url": "https://swumetastats.com/api-docs"
    },
    "license": {
      "name": "Data sourced from Melee.gg tournament results"
    }
  },
  "servers": [
    {
      "url": "https://swumetastats.com",
      "description": "Production"
    }
  ],
  "tags": [
    { "name": "Meta", "description": "Meta boundary windows" },
    { "name": "Archetypes", "description": "Leader + base combination statistics" },
    { "name": "Tournaments", "description": "Tournament listings" },
    { "name": "Decklists", "description": "Individual deck entries" },
    { "name": "Cards", "description": "Card data and usage statistics" },
    { "name": "Matchups", "description": "Head-to-head matchup win rates" },
    { "name": "Tier List", "description": "KyberScore and win rate rankings" },
    { "name": "Leader Trends", "description": "Weekly leader performance trends" },
    { "name": "Players", "description": "Player standings and search" }
  ],
  "paths": {
    "/api/meta-boundaries": {
      "get": {
        "tags": ["Meta"],
        "operationId": "getMetaBoundaries",
        "summary": "List meta boundary windows",
        "description": "Returns all meta boundary windows (sets and balance patches). Each boundary defines a date range used to scope statistics throughout the site.",
        "parameters": [
          { "$ref": "#/components/parameters/format" }
        ],
        "responses": {
          "200": {
            "description": "Array of meta boundary objects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/MetaBoundary" }
                },
                "example": [
                  { "start": "2025-11-07", "end": "2026-03-12", "setId": "SEC", "label": "Secrets of Power" },
                  { "start": "2026-03-13", "end": null, "setId": "LAW", "label": "A Lawless Time" }
                ]
              }
            }
          }
        }
      }
    },
    "/api/archetypes": {
      "get": {
        "tags": ["Archetypes"],
        "operationId": "listArchetypes",
        "summary": "List archetype statistics",
        "description": "Returns aggregated statistics for all archetypes within the specified meta window. An archetype is a unique leader + base combination.",
        "parameters": [
          { "$ref": "#/components/parameters/format" },
          { "$ref": "#/components/parameters/startDate" },
          { "$ref": "#/components/parameters/endDate" },
          {
            "name": "leaderAspect",
            "in": "query",
            "description": "Comma-separated aspect filter for leaders (e.g. aggression,command)",
            "schema": { "type": "string" }
          },
          {
            "name": "baseAspect",
            "in": "query",
            "description": "Comma-separated aspect filter for bases",
            "schema": { "type": "string" }
          },
          {
            "name": "placement",
            "in": "query",
            "description": "Filter by finishing placement",
            "schema": { "type": "string", "enum": ["all", "winners", "top8", "top16", "top32"], "default": "all" }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Filter by leader or base name",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Archetype stats and per-leader aggregates",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ArchetypeListResponse" }
              }
            }
          }
        }
      }
    },
    "/api/archetypes/{leader}/{base}": {
      "get": {
        "tags": ["Archetypes"],
        "operationId": "getArchetypeDetail",
        "summary": "Get archetype detail",
        "description": "Returns detailed statistics for a single archetype including card breakdowns, matchup data, and recent decklists. The leader and base values are URL-encoded card names (spaces → %20). The pipe character (|) can be encoded as %7C or omitted — the API uses fuzzy matching to resolve the correct card name.",
        "parameters": [
          {
            "name": "leader",
            "in": "path",
            "required": true,
            "description": "URL-encoded leader card name (e.g. Han%20Solo%20%7C%20Reluctant%20Hero)",
            "schema": { "type": "string" }
          },
          {
            "name": "base",
            "in": "path",
            "required": true,
            "description": "URL-encoded base card name or base group label (e.g. Vigilance%2030%20HP)",
            "schema": { "type": "string" }
          },
          { "$ref": "#/components/parameters/format" },
          { "$ref": "#/components/parameters/startDate" },
          { "$ref": "#/components/parameters/endDate" }
        ],
        "responses": {
          "200": {
            "description": "Full archetype detail with card stats and matchups",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ArchetypeDetailResponse" }
              }
            }
          }
        }
      }
    },
    "/api/archetype-trends": {
      "get": {
        "tags": ["Archetypes"],
        "operationId": "getArchetypeTrends",
        "summary": "Get archetype weekly trends",
        "description": "Returns weekly time-series data for one or more archetypes across various metrics.",
        "parameters": [
          { "$ref": "#/components/parameters/format" },
          { "$ref": "#/components/parameters/startDate" },
          { "$ref": "#/components/parameters/endDate" },
          {
            "name": "metrics",
            "in": "query",
            "description": "Comma-separated metrics to include",
            "schema": { "type": "string", "example": "winrate,metashare,top8" }
          },
          {
            "name": "topCount",
            "in": "query",
            "description": "Limit to top N archetypes by meta share",
            "schema": { "type": "integer", "default": 10 }
          },
          {
            "name": "leaderName",
            "in": "query",
            "description": "Filter to a specific leader card name",
            "schema": { "type": "string" }
          },
          {
            "name": "baseName",
            "in": "query",
            "description": "Filter to a specific base card name",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Weekly trend data per archetype",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ArchetypeTrendsResponse" }
              }
            }
          }
        }
      }
    },
    "/api/tournaments": {
      "get": {
        "tags": ["Tournaments"],
        "operationId": "listTournaments",
        "summary": "List tournaments",
        "description": "Returns a paginated list of tournaments. Providing search or meleeId returns a flat array instead of a paginated object.",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "description": "Search by tournament name",
            "schema": { "type": "string" }
          },
          {
            "name": "meleeId",
            "in": "query",
            "description": "Look up a specific tournament by its Melee.gg ID",
            "schema": { "type": "integer" }
          },
          { "$ref": "#/components/parameters/format" },
          { "$ref": "#/components/parameters/startDate" },
          { "$ref": "#/components/parameters/endDate" },
          { "$ref": "#/components/parameters/skip" },
          { "$ref": "#/components/parameters/take" }
        ],
        "responses": {
          "200": {
            "description": "Paginated tournament list, or flat array when using search/meleeId",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    { "$ref": "#/components/schemas/TournamentListResponse" },
                    { "type": "array", "items": { "$ref": "#/components/schemas/TournamentSummary" } }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/decklists": {
      "get": {
        "tags": ["Decklists"],
        "operationId": "listDecklists",
        "summary": "List decklists",
        "description": "Returns a paginated list of decklists with full card contents and optional filters.",
        "parameters": [
          { "$ref": "#/components/parameters/format" },
          { "$ref": "#/components/parameters/startDate" },
          { "$ref": "#/components/parameters/endDate" },
          {
            "name": "leaderName",
            "in": "query",
            "description": "Filter by leader card name",
            "schema": { "type": "string" }
          },
          {
            "name": "baseName",
            "in": "query",
            "description": "Filter by base card name",
            "schema": { "type": "string" }
          },
          {
            "name": "leaderAspects",
            "in": "query",
            "description": "Comma-separated leader aspects",
            "schema": { "type": "string" }
          },
          {
            "name": "baseAspects",
            "in": "query",
            "description": "Comma-separated base aspects",
            "schema": { "type": "string" }
          },
          {
            "name": "placement",
            "in": "query",
            "description": "Filter by finishing placement",
            "schema": { "type": "string", "enum": ["all", "winners", "top8"], "default": "all" }
          },
          {
            "name": "tournamentId",
            "in": "query",
            "description": "Filter to a specific tournament",
            "schema": { "type": "integer" }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Search by player name",
            "schema": { "type": "string" }
          },
          { "$ref": "#/components/parameters/skip" },
          { "$ref": "#/components/parameters/take" }
        ],
        "responses": {
          "200": {
            "description": "Paginated decklists with card contents",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/DecklistListResponse" }
              }
            }
          }
        }
      }
    },
    "/api/cards": {
      "get": {
        "tags": ["Cards"],
        "operationId": "listCards",
        "summary": "List cards",
        "description": "Returns card data. The type parameter is required and controls the response shape. Use type=all for the full card database with optional usage stats.",
        "parameters": [
          { "$ref": "#/components/parameters/format" },
          {
            "name": "type",
            "in": "query",
            "required": true,
            "description": "Response type",
            "schema": { "type": "string", "enum": ["leaders", "bases", "all"] }
          },
          {
            "name": "includeUsage",
            "in": "query",
            "description": "Include usage statistics when type=all",
            "schema": { "type": "boolean" }
          },
          {
            "name": "sortBy",
            "in": "query",
            "description": "Sort field",
            "schema": { "type": "string", "enum": ["name", "cost", "usage", "winrate"] }
          },
          {
            "name": "sortDir",
            "in": "query",
            "schema": { "type": "string", "enum": ["asc", "desc"] }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Filter by card name",
            "schema": { "type": "string" }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page index (0-based)",
            "schema": { "type": "integer", "default": 0 }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": { "type": "integer", "default": 20, "maximum": 200 }
          },
          { "$ref": "#/components/parameters/startDate" },
          { "$ref": "#/components/parameters/endDate" }
        ],
        "responses": {
          "200": {
            "description": "Leader array, base array, or paginated card list depending on type",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "description": "type=leaders",
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/LeaderCard" }
                    },
                    {
                      "description": "type=bases",
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/BaseCard" }
                    },
                    {
                      "description": "type=all",
                      "$ref": "#/components/schemas/CardListResponse"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/matchups": {
      "get": {
        "tags": ["Matchups"],
        "operationId": "getMatchups",
        "summary": "Get matchup matrix",
        "description": "Returns pairwise matchup win rates between archetypes for the specified meta window.",
        "parameters": [
          { "$ref": "#/components/parameters/format" },
          { "$ref": "#/components/parameters/startDate" },
          { "$ref": "#/components/parameters/endDate" },
          {
            "name": "placement",
            "in": "query",
            "description": "Restrict to a finishing placement bracket",
            "schema": { "type": "string", "enum": ["winners", "top8"] }
          },
          {
            "name": "minPlayers",
            "in": "query",
            "description": "Minimum games played required to include a matchup pair",
            "schema": { "type": "integer", "default": 5 }
          },
          {
            "name": "tournamentId",
            "in": "query",
            "description": "Scope to a single tournament",
            "schema": { "type": "integer" }
          }
        ],
        "responses": {
          "200": {
            "description": "Matchup win rate data and leader sets map",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/MatchupResponse" }
              }
            }
          }
        }
      }
    },
    "/api/tierlist": {
      "get": {
        "tags": ["Tier List"],
        "operationId": "getTierlist",
        "summary": "Get tier list",
        "description": "Returns tier list data. The mode parameter is required and controls the response shape.",
        "parameters": [
          {
            "name": "mode",
            "in": "query",
            "required": true,
            "description": "kyberscore: ranked by KyberScore algorithm; raw: ranked by win rate; weeks: list of available week dates; live: single-week snapshot; snapshot: single-week snapshot payload",
            "schema": { "type": "string", "enum": ["kyberscore", "raw", "weeks", "live", "snapshot"] }
          },
          {
            "name": "format",
            "in": "query",
            "description": "Game format filter",
            "schema": { "type": "string", "enum": ["Premier", "Eternal"], "default": "Premier" }
          },
          { "$ref": "#/components/parameters/startDate" },
          { "$ref": "#/components/parameters/endDate" },
          {
            "name": "date",
            "in": "query",
            "description": "Shorthand meta boundary start date override for mode=raw or mode=kyberscore (YYYY-MM-DD)",
            "schema": { "type": "string", "format": "date" }
          },
          {
            "name": "week",
            "in": "query",
            "description": "Week anchor date for mode=live or mode=snapshot (YYYY-MM-DD)",
            "schema": { "type": "string", "format": "date" }
          }
        ],
        "responses": {
          "200": {
            "description": "Tier list data — shape depends on mode",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "description": "mode=weeks — list of available Monday dates",
                      "type": "array",
                      "items": { "type": "string", "format": "date" }
                    },
                    {
                      "description": "mode=raw",
                      "$ref": "#/components/schemas/RawTierlistResponse"
                    },
                    {
                      "description": "mode=kyberscore",
                      "$ref": "#/components/schemas/KyberscoreTierlistResponse"
                    },
                    {
                      "description": "mode=live or mode=snapshot",
                      "$ref": "#/components/schemas/LiveTierlistResponse"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/leader-trends": {
      "get": {
        "tags": ["Leader Trends"],
        "operationId": "getLeaderTrends",
        "summary": "Get leader weekly trends",
        "description": "Returns weekly time-series trend data per leader card.",
        "parameters": [
          { "$ref": "#/components/parameters/format" },
          { "$ref": "#/components/parameters/startDate" },
          { "$ref": "#/components/parameters/endDate" },
          {
            "name": "metric",
            "in": "query",
            "description": "Metric to return per leader per week",
            "schema": {
              "type": "string",
              "enum": ["winrate", "conversion", "metashare", "wins", "top8", "decks", "losses"],
              "default": "winrate"
            }
          },
          {
            "name": "leaders",
            "in": "query",
            "description": "Comma-separated leader names to include (defaults to top leaders by meta share)",
            "schema": { "type": "string" }
          },
          {
            "name": "topCount",
            "in": "query",
            "description": "Return top N leaders by meta share",
            "schema": { "type": "integer", "default": 10 }
          }
        ],
        "responses": {
          "200": {
            "description": "Weekly leader trend data",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/LeaderTrendsResponse" }
              }
            }
          }
        }
      }
    },
    "/api/players/search": {
      "get": {
        "tags": ["Players"],
        "operationId": "searchPlayers",
        "summary": "Search players",
        "description": "Searches and paginates players who have recorded tournament standings.",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "description": "Filter by player name or username",
            "schema": { "type": "string" }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sort order",
            "schema": {
              "type": "string",
              "enum": ["alphabetical", "wins", "tournaments", "conversion"],
              "default": "alphabetical"
            }
          },
          { "$ref": "#/components/parameters/skip" },
          { "$ref": "#/components/parameters/take" }
        ],
        "responses": {
          "200": {
            "description": "Paginated player list",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PlayerSearchResponse" }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "format": {
        "name": "format",
        "in": "query",
        "description": "Game format filter. Premier includes legacy null-format tournaments.",
        "schema": { "type": "string", "enum": ["Premier", "Eternal"], "default": "Premier" }
      },
      "startDate": {
        "name": "startDate",
        "in": "query",
        "description": "Start of meta window (YYYY-MM-DD, e.g. 2025-01-01). Use /api/meta-boundaries to discover valid ranges.",
        "schema": { "type": "string", "format": "date" }
      },
      "endDate": {
        "name": "endDate",
        "in": "query",
        "description": "End of meta window (YYYY-MM-DD)",
        "schema": { "type": "string", "format": "date" }
      },
      "skip": {
        "name": "skip",
        "in": "query",
        "description": "Pagination offset",
        "schema": { "type": "integer", "default": 0 }
      },
      "take": {
        "name": "take",
        "in": "query",
        "description": "Page size",
        "schema": { "type": "integer", "default": 20 }
      }
    },
    "schemas": {
      "MetaBoundary": {
        "type": "object",
        "properties": {
          "start": { "type": "string", "format": "date", "description": "Window start date" },
          "end": { "type": "string", "format": "date", "description": "Window end date" },
          "setId": { "type": "string", "description": "Card set code (e.g. SHD, TWI, JTL)" },
          "label": { "type": "string", "description": "Human-readable window name" }
        }
      },
      "ArchetypeStat": {
        "type": "object",
        "properties": {
          "leaderName": { "type": "string" },
          "baseName": { "type": "string", "description": "Display name, may be a base group (e.g. Vigilance 30 HP)" },
          "baseCardName": { "type": "string", "description": "Actual card name from DB" },
          "leaderAspect": { "type": "string", "nullable": true },
          "baseAspect": { "type": "string", "nullable": true },
          "leaderSet": { "type": "string", "nullable": true },
          "baseSet": { "type": "string", "nullable": true },
          "baseGroup": { "type": "string", "nullable": true },
          "total": { "type": "string", "description": "Total deck count (BigInt serialized as string)" },
          "top8": { "type": "string", "description": "Top 8 count" },
          "tournamentWins": { "type": "string", "description": "Tournament wins (standing = 1)" },
          "wins": { "type": "integer" },
          "losses": { "type": "integer" },
          "draws": { "type": "integer" },
          "games": { "type": "integer" },
          "winRate": { "type": "number", "format": "float", "minimum": 0, "maximum": 1 },
          "metaShare": { "type": "number", "format": "float", "minimum": 0, "maximum": 1 }
        }
      },
      "ArchetypeListResponse": {
        "type": "object",
        "properties": {
          "archetypes": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ArchetypeStat" }
          },
          "leaderStats": {
            "type": "object",
            "description": "Per-leader aggregate stats keyed by leader name",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "wins": { "type": "integer" },
                "losses": { "type": "integer" },
                "draws": { "type": "integer" },
                "games": { "type": "integer" },
                "winRate": { "type": "number" },
                "metaShare": { "type": "number" },
                "deckCount": { "type": "integer" }
              }
            }
          }
        }
      },
      "CardStat": {
        "type": "object",
        "properties": {
          "cardName": { "type": "string" },
          "raw3": { "type": "integer", "description": "Number of decks running 3 copies" },
          "pct3": { "type": "number", "description": "Percentage of decks running 3 copies" },
          "raw2": { "type": "integer" },
          "pct2": { "type": "number" },
          "raw1": { "type": "integer" },
          "pct1": { "type": "number" }
        }
      },
      "CardGroups": {
        "type": "object",
        "properties": {
          "Core": { "type": "array", "items": { "$ref": "#/components/schemas/CardStat" } },
          "Popular": { "type": "array", "items": { "$ref": "#/components/schemas/CardStat" } },
          "Flex": { "type": "array", "items": { "$ref": "#/components/schemas/CardStat" } }
        }
      },
      "MatchupEntry": {
        "type": "object",
        "properties": {
          "oppLeader": { "type": "string" },
          "oppBase": { "type": "string" },
          "games": { "type": "integer" },
          "wins": { "type": "integer" },
          "losses": { "type": "integer" },
          "draws": { "type": "integer" },
          "leaderAspect": { "type": "string", "nullable": true },
          "baseAspect": { "type": "string", "nullable": true }
        }
      },
      "ArchetypeDetailResponse": {
        "type": "object",
        "properties": {
          "notFound": { "type": "boolean" },
          "leaderName": { "type": "string" },
          "baseName": { "type": "string" },
          "baseGroupLabel": { "type": "string" },
          "totalDecks": { "type": "integer" },
          "totalMetaDecks": { "type": "integer" },
          "mainboardGroups": { "$ref": "#/components/schemas/CardGroups" },
          "sideboardGroups": { "$ref": "#/components/schemas/CardGroups" },
          "mainboardGroupsTop8": { "$ref": "#/components/schemas/CardGroups" },
          "mainboardGroupsWinners": { "$ref": "#/components/schemas/CardGroups" },
          "deckCounts": {
            "type": "object",
            "properties": {
              "all": { "type": "integer" },
              "top8": { "type": "integer" },
              "winners": { "type": "integer" }
            }
          },
          "combinedAspects": { "type": "array", "items": { "type": "string" } },
          "leaderImageUrl": { "type": "string", "nullable": true },
          "leaderBackImageUrl": { "type": "string", "nullable": true },
          "baseImageUrl": { "type": "string", "nullable": true },
          "archetypeStats": {
            "type": "object",
            "properties": {
              "conversion": { "type": "number" },
              "totalWins": { "type": "integer" },
              "totalLosses": { "type": "integer" },
              "totalDraws": { "type": "integer" },
              "totalGames": { "type": "integer" },
              "overallWinRate": { "type": "number", "minimum": 0, "maximum": 1 },
              "matchups": { "type": "array", "items": { "$ref": "#/components/schemas/MatchupEntry" } }
            }
          },
          "decklistsForCombo": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "integer" },
                "guid": { "type": "string" },
                "standing": { "type": "integer", "nullable": true },
                "tournament": { "type": "object", "properties": { "name": { "type": "string" } } }
              }
            }
          }
        }
      },
      "ArchetypeTrendsResponse": {
        "type": "object",
        "properties": {
          "trends": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": { "type": "string", "format": "date", "description": "Week start (Monday)" },
                "archetypes": {
                  "type": "object",
                  "description": "Keyed by archetype display name → metric name → value",
                  "additionalProperties": {
                    "type": "object",
                    "additionalProperties": { "type": "number" }
                  }
                }
              }
            }
          },
          "archetypes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": { "type": "string" },
                "leaderName": { "type": "string" },
                "baseName": { "type": "string" },
                "displayName": { "type": "string" }
              }
            }
          },
          "archetypeAspects": {
            "type": "object",
            "description": "Display name → leader aspect",
            "additionalProperties": { "type": "string" }
          }
        }
      },
      "TournamentSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" },
          "startDate": { "type": "string", "format": "date-time" },
          "playerCount": { "type": "integer", "nullable": true },
          "meleeId": { "type": "integer", "nullable": true }
        }
      },
      "TournamentListResponse": {
        "type": "object",
        "properties": {
          "tournaments": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/TournamentSummary" }
          },
          "totalCount": { "type": "integer" }
        }
      },
      "DecklistCard": {
        "type": "object",
        "properties": {
          "count": { "type": "integer" },
          "section": { "type": "string", "description": "Leader, Base, MainBoard, or SideBoard" },
          "cardName": { "type": "string" },
          "card": {
            "type": "object",
            "nullable": true,
            "properties": {
              "name": { "type": "string" },
              "aspect": { "type": "string", "nullable": true },
              "cost": { "type": "integer", "nullable": true },
              "type": { "type": "string", "nullable": true },
              "imageUrl": { "type": "string", "nullable": true },
              "frontText": { "type": "string", "nullable": true },
              "power": { "type": "string", "nullable": true },
              "hp": { "type": "integer", "nullable": true }
            }
          }
        }
      },
      "DecklistEntry": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "guid": { "type": "string" },
          "standing": { "type": "integer", "nullable": true },
          "leaderName": { "type": "string", "nullable": true },
          "baseName": { "type": "string", "nullable": true },
          "leaderCard": {
            "type": "object",
            "nullable": true,
            "properties": {
              "name": { "type": "string" },
              "aspect": { "type": "string", "nullable": true },
              "set": { "type": "string", "nullable": true }
            }
          },
          "baseCard": {
            "type": "object",
            "nullable": true,
            "properties": {
              "name": { "type": "string" },
              "aspect": { "type": "string", "nullable": true },
              "set": { "type": "string", "nullable": true },
              "baseGroup": { "type": "string", "nullable": true }
            }
          },
          "tournament": {
            "type": "object",
            "nullable": true,
            "properties": {
              "name": { "type": "string" },
              "startDate": { "type": "string", "format": "date-time" }
            }
          },
          "player": {
            "type": "object",
            "nullable": true,
            "properties": { "name": { "type": "string" } }
          },
          "cards": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/DecklistCard" }
          }
        }
      },
      "DecklistListResponse": {
        "type": "object",
        "properties": {
          "decklists": { "type": "array", "items": { "$ref": "#/components/schemas/DecklistEntry" } },
          "totalCount": { "type": "integer" }
        }
      },
      "LeaderCard": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "aspect": { "type": "string", "nullable": true },
          "set": { "type": "string", "nullable": true },
          "imageUrl": { "type": "string", "nullable": true }
        }
      },
      "BaseCard": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "aspect": { "type": "string" },
          "set": { "type": "string" },
          "imageUrl": { "type": "string" },
          "baseGroup": { "type": "string" },
          "displayName": { "type": "string" }
        }
      },
      "CardUsage": {
        "type": "object",
        "properties": {
          "appearances": { "type": "integer" },
          "totalUsage": { "type": "number", "description": "Percentage of decks containing this card" },
          "pct1": { "type": "number", "description": "% running exactly 1 copy" },
          "pct2": { "type": "number", "description": "% running exactly 2 copies" },
          "pct3": { "type": "number", "description": "% running 3+ copies" }
        }
      },
      "Card": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "aspect": { "type": "string", "nullable": true },
          "cost": { "type": "integer", "nullable": true },
          "type": { "type": "string", "nullable": true },
          "rarity": { "type": "string", "nullable": true },
          "set": { "type": "string", "nullable": true },
          "arena": { "type": "string", "nullable": true },
          "trait": { "type": "string", "nullable": true },
          "frontText": { "type": "string", "nullable": true },
          "power": { "type": "string", "nullable": true },
          "hp": { "type": "integer", "nullable": true },
          "unique": { "type": "boolean", "nullable": true },
          "imageUrl": { "type": "string", "nullable": true },
          "backImageUrl": { "type": "string", "nullable": true },
          "foilImageUrl": { "type": "string", "nullable": true },
          "hyperspaceImageUrl": { "type": "string", "nullable": true },
          "showcaseImageUrl": { "type": "string", "nullable": true },
          "usage": { "$ref": "#/components/schemas/CardUsage", "nullable": true },
          "winRate": { "type": "number", "nullable": true, "minimum": 0, "maximum": 1 }
        }
      },
      "CardListResponse": {
        "type": "object",
        "properties": {
          "cards": { "type": "array", "items": { "$ref": "#/components/schemas/Card" } },
          "hasMore": { "type": "boolean" },
          "total": { "type": "integer" }
        }
      },
      "MatchupRow": {
        "type": "object",
        "properties": {
          "archetype": { "type": "string", "description": "Leader / Base display string" },
          "opponent": { "type": "string" },
          "leader": { "type": "string" },
          "base": { "type": "string" },
          "baseGroup": { "type": "string", "nullable": true },
          "aspect": { "type": "string", "description": "Base aspect" },
          "leaderAspect": { "type": "string" },
          "opponentLeader": { "type": "string" },
          "opponentBase": { "type": "string" },
          "opponentBaseGroup": { "type": "string", "nullable": true },
          "opponentAspect": { "type": "string" },
          "opponentLeaderAspect": { "type": "string" },
          "wins": { "type": "integer" },
          "losses": { "type": "integer" },
          "draws": { "type": "integer" },
          "games": { "type": "integer" },
          "winRate": { "type": "number", "minimum": 0, "maximum": 1 },
          "gameWins": { "type": "integer" },
          "gameLosses": { "type": "integer" },
          "gameDraws": { "type": "integer" },
          "totalGames": { "type": "integer" },
          "gameWinRate": { "type": "number", "minimum": 0, "maximum": 1 }
        }
      },
      "MatchupResponse": {
        "type": "object",
        "properties": {
          "matchups": { "type": "array", "items": { "$ref": "#/components/schemas/MatchupRow" } },
          "leaderSets": {
            "type": "object",
            "description": "Leader name → set code",
            "additionalProperties": { "type": "string" }
          }
        }
      },
      "RawTierlistEntry": {
        "type": "object",
        "properties": {
          "archetypeId": { "type": "string" },
          "archetypeName": { "type": "string" },
          "leaderName": { "type": "string" },
          "leaderAspect": { "type": "string", "nullable": true },
          "baseName": { "type": "string" },
          "baseAspect": { "type": "string", "nullable": true },
          "baseGroup": { "type": "string", "nullable": true },
          "deckCount": { "type": "integer" },
          "top8Count": { "type": "integer" },
          "top4Count": { "type": "integer" },
          "winCount": { "type": "integer" },
          "wins": { "type": "integer" },
          "losses": { "type": "integer" },
          "draws": { "type": "integer" },
          "games": { "type": "integer" },
          "winRate": { "type": "number", "minimum": 0, "maximum": 1 },
          "conversion": { "type": "number", "minimum": 0, "maximum": 1 },
          "metaShare": { "type": "number", "minimum": 0, "maximum": 1 },
          "t8Rate": { "type": "number", "minimum": 0, "maximum": 1 },
          "t4Rate": { "type": "number", "minimum": 0, "maximum": 1 }
        }
      },
      "RawTierlistResponse": {
        "type": "object",
        "properties": {
          "tierlist": { "type": "array", "items": { "$ref": "#/components/schemas/RawTierlistEntry" } }
        }
      },
      "KyberscoreEntry": {
        "type": "object",
        "properties": {
          "archetypeId": { "type": "string" },
          "name": { "type": "string" },
          "leaderName": { "type": "string" },
          "leaderAspect": { "type": "string", "nullable": true },
          "baseName": { "type": "string" },
          "baseAspect": { "type": "string", "nullable": true },
          "baseGroup": { "type": "string", "nullable": true },
          "winRate": { "type": "number" },
          "wins": { "type": "integer" },
          "losses": { "type": "integer" },
          "draws": { "type": "integer" },
          "games": { "type": "integer" },
          "deckCount": { "type": "integer" },
          "conversion": { "type": "number" },
          "metaShare": { "type": "number" },
          "score": { "type": "number", "description": "KyberScore composite ranking value" },
          "tier": { "type": "string", "description": "Tier label: S, A, B, C, or D" },
          "recentWinRate": { "type": "number" },
          "trend": { "type": "number" },
          "sampleConfidence": { "type": "number" }
        }
      },
      "KyberscoreTierlistResponse": {
        "type": "object",
        "properties": {
          "tierlist": { "type": "array", "items": { "$ref": "#/components/schemas/KyberscoreEntry" } }
        }
      },
      "LiveTierlistResponse": {
        "type": "object",
        "properties": {
          "weekStart": { "type": "string", "format": "date" },
          "tournamentCount": { "type": "integer" },
          "snapshots": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "archetypeName": { "type": "string" },
                "leaderName": { "type": "string" },
                "baseName": { "type": "string" },
                "baseGroup": { "type": "string", "nullable": true },
                "leaderAspect": { "type": "string", "nullable": true },
                "baseAspect": { "type": "string", "nullable": true },
                "archetypeId": { "type": "string" },
                "wins": { "type": "integer" },
                "losses": { "type": "integer" },
                "draws": { "type": "integer" },
                "games": { "type": "integer" },
                "winRate": { "type": "number" },
                "conversion": { "type": "number" },
                "metaShare": { "type": "number" },
                "top8Count": { "type": "integer" },
                "deckCount": { "type": "integer" }
              }
            }
          }
        }
      },
      "LeaderTrendsResponse": {
        "type": "object",
        "properties": {
          "trends": {
            "type": "array",
            "description": "Each entry is a week. Keys beyond 'date' are leader names with metric values.",
            "items": {
              "type": "object",
              "properties": {
                "date": { "type": "string", "format": "date", "description": "Week start (Monday)" }
              },
              "additionalProperties": {
                "oneOf": [
                  { "type": "number" },
                  { "type": "null" }
                ]
              }
            }
          },
          "leaders": { "type": "array", "items": { "type": "string" } },
          "leaderAspects": {
            "type": "object",
            "description": "Leader name → aspect string",
            "additionalProperties": { "type": "string" }
          },
          "leaderSets": {
            "type": "object",
            "description": "Leader name → set code",
            "additionalProperties": { "type": "string" }
          },
          "weeks": { "type": "integer", "description": "Total weeks in the date range" }
        }
      },
      "PlayerSearchResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "integer" },
                "name": { "type": "string" },
                "username": { "type": "string" },
                "meleeId": { "type": "integer", "nullable": true },
                "winCount": { "type": "integer", "description": "Tournament wins (standing = 1)" },
                "top8Count": { "type": "integer" },
                "tournamentCount": { "type": "integer" }
              }
            }
          },
          "totalCount": { "type": "integer" }
        }
      }
    }
  }
}
