{
  "openapi": "3.1.0",
  "info": {
    "title": "Stats API",
    "version": "1.0.0-beta",
    "summary": "A cache-first football data API with stable public identifiers.",
    "description": "Retrieve normalized football competitions, seasons, teams, fixtures, results, and explicit coverage. Customer requests are served from Stats API storage and never call an upstream provider synchronously.",
    "contact": {
      "url": "https://stats-api.com/docs"
    }
  },
  "servers": [
    {
      "url": "https://stats-api.com/api/v1",
      "description": "Production"
    },
    {
      "url": "http://localhost:8080/api/v1",
      "description": "Local development"
    }
  ],
  "tags": [
    {"name": "Platform", "description": "Service health."},
    {"name": "Coverage", "description": "Data availability by competition."},
    {"name": "Competitions", "description": "Football competitions and seasons."},
    {"name": "Matches", "description": "Scheduled and completed matches."},
    {"name": "Teams", "description": "Football team lookup."}
  ],
  "security": [{"bearerAuth": []}],
  "paths": {
    "/health": {
      "get": {
        "tags": ["Platform"],
        "operationId": "getHealth",
        "summary": "Check service health",
        "description": "Reports API version and dependency health. Authentication is not required.",
        "security": [],
        "responses": {
          "200": {
            "description": "All dependencies are healthy.",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HealthResponse"}}}
          },
          "503": {
            "description": "At least one dependency is degraded.",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HealthResponse"}}}
          }
        }
      }
    },
    "/coverage/summary": {
      "get": {
        "tags": ["Coverage"],
        "operationId": "getCoverageSummary",
        "summary": "Get coverage totals",
        "description": "Returns current counts from the normalized Stats API database.",
        "responses": {
          "200": {
            "description": "Coverage totals.",
            "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CoverageSummaryResponse"}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/coverage/leagues": {
      "get": {
        "tags": ["Coverage"],
        "operationId": "listCoveredCompetitions",
        "summary": "List covered competitions",
        "description": "Lists competitions with explicit capability flags. A false flag means the data is not currently sold.",
        "parameters": [
          {"$ref": "#/components/parameters/Page"},
          {"$ref": "#/components/parameters/Limit"}
        ],
        "responses": {
          "200": {
            "description": "Paginated coverage list.",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/CoverageLeague"}}, "meta": {"$ref": "#/components/schemas/PaginationMeta"}}, "required": ["data", "meta"]}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/coverage/leagues/{competition_id}": {
      "get": {
        "tags": ["Coverage"],
        "operationId": "getCoveredCompetition",
        "summary": "Get competition coverage",
        "description": "Returns available seasons and capability flags for one competition.",
        "parameters": [{"$ref": "#/components/parameters/CompetitionId"}],
        "responses": {
          "200": {
            "description": "Competition coverage.",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"type": "object", "properties": {"competition": {"$ref": "#/components/schemas/Competition"}, "seasons": {"type": "array", "items": {"$ref": "#/components/schemas/Season"}}, "available": {"$ref": "#/components/schemas/Capabilities"}}, "required": ["competition", "seasons", "available"]}}, "required": ["data"]}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/football/competitions": {
      "get": {
        "tags": ["Competitions"],
        "operationId": "listCompetitions",
        "summary": "List competitions",
        "description": "Returns active football competitions ordered by country and name.",
        "parameters": [
          {"name": "country_code", "in": "query", "description": "ISO 3166-1 alpha-2 country code.", "schema": {"type": "string", "minLength": 2, "maxLength": 2}, "example": "GB"},
          {"name": "q", "in": "query", "description": "Case-insensitive competition-name search.", "schema": {"type": "string", "maxLength": 100}, "example": "premier"},
          {"$ref": "#/components/parameters/Page"},
          {"$ref": "#/components/parameters/Limit"}
        ],
        "responses": {
          "200": {
            "description": "Paginated competition collection.",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/Competition"}}, "meta": {"$ref": "#/components/schemas/PaginationMeta"}}, "required": ["data", "meta"]}, "examples": {"success": {"value": {"data": [{"id": "comp_4e223f6d8b84", "slug": "premier-league-gb", "name": "Premier League", "country": {"name": "England", "code": "GB"}, "type": "league", "gender": "men", "logo_url": null, "season_count": 5}], "meta": {"page": 1, "limit": 25, "request_id": "31de9ee84c91ab11"}}}}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/football/competitions/{competition_id}": {
      "get": {
        "tags": ["Competitions"],
        "operationId": "getCompetition",
        "summary": "Get competition details",
        "description": "Retrieves one competition by its stable Stats API identifier.",
        "parameters": [{"$ref": "#/components/parameters/CompetitionId"}],
        "responses": {
          "200": {
            "description": "Competition details.",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"$ref": "#/components/schemas/Competition"}}, "required": ["data"]}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/football/competitions/{competition_id}/seasons": {
      "get": {
        "tags": ["Competitions"],
        "operationId": "listCompetitionSeasons",
        "summary": "List competition seasons",
        "description": "Returns seasons newest first, including team and match counts.",
        "parameters": [{"$ref": "#/components/parameters/CompetitionId"}],
        "responses": {
          "200": {
            "description": "Competition seasons.",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/Season"}}, "meta": {"type": "object", "properties": {"count": {"type": "integer"}}}, "required": ["data", "meta"]}}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/football/matches": {
      "get": {
        "tags": ["Matches"],
        "operationId": "listMatches",
        "summary": "List matches",
        "description": "Lists scheduled and completed matches with optional competition, season, team, status, and date filters.",
        "parameters": [
          {"name": "competition_id", "in": "query", "schema": {"type": "string"}, "example": "comp_4e223f6d8b84"},
          {"name": "season_id", "in": "query", "schema": {"type": "string"}, "example": "season_77c2d67f05df"},
          {"name": "team_id", "in": "query", "schema": {"type": "string"}, "example": "team_26a5fd461c18"},
          {"name": "status", "in": "query", "schema": {"type": "string", "enum": ["scheduled", "live", "finished", "postponed", "canceled", "unknown"]}},
          {"name": "date_from", "in": "query", "schema": {"type": "string", "format": "date"}},
          {"name": "date_to", "in": "query", "schema": {"type": "string", "format": "date"}},
          {"$ref": "#/components/parameters/Page"},
          {"$ref": "#/components/parameters/Limit"}
        ],
        "responses": {
          "200": {
            "description": "Paginated match collection.",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/Match"}}, "meta": {"$ref": "#/components/schemas/PaginationMeta"}}, "required": ["data", "meta"]}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/football/matches/{match_id}": {
      "get": {
        "tags": ["Matches"],
        "operationId": "getMatch",
        "summary": "Get match details",
        "description": "Retrieves one fixture or result by its stable Stats API identifier.",
        "parameters": [{"name": "match_id", "in": "path", "required": true, "schema": {"type": "string", "pattern": "^match_"}, "example": "match_b7f18ac4cc11"}],
        "responses": {
          "200": {
            "description": "Match details.",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"$ref": "#/components/schemas/Match"}}, "required": ["data"]}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/football/teams": {
      "get": {
        "tags": ["Teams"],
        "operationId": "listTeams",
        "summary": "List and search teams",
        "description": "Lists teams alphabetically. Use q for a case-insensitive name search.",
        "parameters": [
          {"name": "q", "in": "query", "schema": {"type": "string", "maxLength": 100}, "example": "city"},
          {"$ref": "#/components/parameters/Page"},
          {"$ref": "#/components/parameters/Limit"}
        ],
        "responses": {
          "200": {
            "description": "Paginated team collection.",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/Team"}}, "meta": {"$ref": "#/components/schemas/PaginationMeta"}}, "required": ["data", "meta"]}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    },
    "/football/teams/{team_id}": {
      "get": {
        "tags": ["Teams"],
        "operationId": "getTeam",
        "summary": "Get team details",
        "description": "Retrieves one team by its stable Stats API identifier.",
        "parameters": [{"name": "team_id", "in": "path", "required": true, "schema": {"type": "string", "pattern": "^team_"}, "example": "team_26a5fd461c18"}],
        "responses": {
          "200": {
            "description": "Team details.",
            "content": {"application/json": {"schema": {"type": "object", "properties": {"data": {"$ref": "#/components/schemas/Team"}}, "required": ["data"]}}}
          },
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "404": {"$ref": "#/components/responses/NotFound"},
          "429": {"$ref": "#/components/responses/RateLimited"}
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Stats API key",
        "description": "A key beginning with sapi_live_ in production or sapi_test_ locally."
      }
    },
    "parameters": {
      "Page": {"name": "page", "in": "query", "description": "One-indexed page number.", "schema": {"type": "integer", "minimum": 1, "default": 1}},
      "Limit": {"name": "limit", "in": "query", "description": "Items per page.", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 25}},
      "CompetitionId": {"name": "competition_id", "in": "path", "required": true, "schema": {"type": "string", "pattern": "^comp_"}, "example": "comp_4e223f6d8b84"}
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, invalid, expired, or inactive API key.",
        "headers": {"WWW-Authenticate": {"schema": {"type": "string"}}},
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}, "example": {"error": {"code": "invalid_api_key", "message": "Provide an active Stats API key in the Authorization Bearer header.", "details": {}}}}}
      },
      "NotFound": {
        "description": "The requested resource does not exist.",
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}
      },
      "RateLimited": {
        "description": "The per-minute rate limit or billing-period quota was exceeded.",
        "headers": {
          "Retry-After": {"schema": {"type": "integer"}},
          "X-RateLimit-Limit": {"schema": {"type": "integer"}},
          "X-RateLimit-Remaining": {"schema": {"type": "integer"}},
          "X-Quota-Limit": {"schema": {"type": "integer"}},
          "X-Quota-Remaining": {"schema": {"type": "integer"}},
          "X-Quota-Reset": {"schema": {"type": "integer"}}
        },
        "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}
      }
    },
    "schemas": {
      "HealthResponse": {
        "type": "object",
        "properties": {
          "status": {"type": "string", "enum": ["ok", "degraded"]},
          "version": {"type": "string", "example": "v1"},
          "time": {"type": "string", "format": "date-time"},
          "checks": {"type": "object", "properties": {"database": {"type": "boolean"}, "cache": {"type": "boolean"}}, "required": ["database", "cache"]}
        },
        "required": ["status", "version", "time", "checks"]
      },
      "Country": {
        "type": "object",
        "properties": {"name": {"type": ["string", "null"]}, "code": {"type": ["string", "null"], "minLength": 2, "maxLength": 2}},
        "required": ["name", "code"]
      },
      "Competition": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "pattern": "^comp_"},
          "slug": {"type": "string"},
          "name": {"type": "string"},
          "country": {"$ref": "#/components/schemas/Country"},
          "type": {"type": "string", "enum": ["league", "cup", "tournament", "unknown"]},
          "gender": {"type": "string", "enum": ["men", "women", "mixed", "unknown"]},
          "logo_url": {"type": ["string", "null"], "format": "uri"},
          "season_count": {"type": "integer", "minimum": 0}
        },
        "required": ["id", "slug", "name", "country", "type", "gender", "logo_url", "season_count"]
      },
      "Season": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "pattern": "^season_"},
          "name": {"type": "string"},
          "starts_on": {"type": ["string", "null"], "format": "date"},
          "ends_on": {"type": ["string", "null"], "format": "date"},
          "is_current": {"type": "boolean"},
          "team_count": {"type": "integer", "minimum": 0},
          "match_count": {"type": "integer", "minimum": 0}
        },
        "required": ["id", "name", "starts_on", "ends_on", "is_current", "team_count", "match_count"]
      },
      "Team": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "pattern": "^team_"},
          "slug": {"type": "string"},
          "name": {"type": "string"},
          "short_name": {"type": ["string", "null"]},
          "country_name": {"type": ["string", "null"]},
          "country_code": {"type": ["string", "null"]},
          "logo_url": {"type": ["string", "null"], "format": "uri"}
        },
        "required": ["id", "slug", "name", "short_name", "country_name", "country_code", "logo_url"]
      },
      "MatchTeam": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "pattern": "^team_"},
          "name": {"type": "string"},
          "logo_url": {"type": ["string", "null"], "format": "uri"},
          "score": {"type": ["integer", "null"], "minimum": 0}
        },
        "required": ["id", "name", "logo_url", "score"]
      },
      "Match": {
        "type": "object",
        "properties": {
          "id": {"type": "string", "pattern": "^match_"},
          "competition": {"type": "object", "properties": {"id": {"type": "string"}, "name": {"type": "string"}}, "required": ["id", "name"]},
          "season": {"type": "object", "properties": {"id": {"type": "string"}, "name": {"type": "string"}}, "required": ["id", "name"]},
          "starts_at": {"type": "string", "format": "date-time"},
          "round": {"type": ["string", "null"]},
          "status": {"type": "string", "enum": ["scheduled", "live", "finished", "postponed", "canceled", "unknown"]},
          "home_team": {"$ref": "#/components/schemas/MatchTeam"},
          "away_team": {"$ref": "#/components/schemas/MatchTeam"},
          "venue": {"oneOf": [{"type": "null"}, {"type": "object", "properties": {"name": {"type": "string"}}, "required": ["name"]}]},
          "updated_at": {"type": ["string", "null"], "format": "date-time"}
        },
        "required": ["id", "competition", "season", "starts_at", "round", "status", "home_team", "away_team", "venue", "updated_at"]
      },
      "Capabilities": {
        "type": "object",
        "properties": {
          "fixtures": {"type": "boolean"},
          "results": {"type": "boolean"},
          "teams": {"type": "boolean"},
          "standings": {"type": "boolean"},
          "players": {"type": "boolean"},
          "live": {"type": "boolean"},
          "odds": {"type": "boolean"}
        },
        "required": ["fixtures", "results", "teams", "standings", "players", "live", "odds"]
      },
      "CoverageLeague": {
        "type": "object",
        "properties": {"competition": {"$ref": "#/components/schemas/Competition"}, "available": {"$ref": "#/components/schemas/Capabilities"}},
        "required": ["competition", "available"]
      },
      "CoverageSummaryResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "competitions": {"type": "integer"},
              "seasons": {"type": "integer"},
              "teams": {"type": "integer"},
              "matches": {"type": "integer"},
              "completed_matches": {"type": "integer"}
            },
            "required": ["competitions", "seasons", "teams", "matches", "completed_matches"]
          }
        },
        "required": ["data"]
      },
      "PaginationMeta": {
        "type": "object",
        "properties": {"page": {"type": "integer"}, "limit": {"type": "integer"}, "request_id": {"type": "string"}},
        "required": ["page", "limit", "request_id"]
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {"code": {"type": "string"}, "message": {"type": "string"}, "details": {"type": "object"}},
            "required": ["code", "message", "details"]
          }
        },
        "required": ["error"]
      }
    }
  }
}
