{
  "openapi": "3.1.0",
  "info": {
    "title": "StrinovaHub API",
    "version": "1.0.0",
    "description": "Strinova match data from replays uploaded to StrinovaHub, public StrinovaHub profiles and the season schedule. Read-only. Docs: https://api.strinovahub.com"
  },
  "servers": [{ "url": "https://api.strinovahub.com/v1" }],
  "security": [{ "bearer": [] }],
  "components": {
    "securitySchemes": { "bearer": { "type": "http", "scheme": "bearer", "description": "API key from Settings › Developer API (shk_live_…)" } },
    "schemas": {
      "Error": { "type": "object", "properties": { "error": { "type": "object", "properties": { "code": { "type": "string" }, "message": { "type": "string" }, "retryAfter": { "type": "integer" } }, "required": ["code", "message"] } } },
      "Season": { "type": "object", "properties": { "code": { "type": "string" }, "title": { "type": "string" }, "startsAt": { "type": "string", "format": "date-time" }, "endsAt": { "type": ["string", "null"], "format": "date-time" }, "current": { "type": "boolean" } } },
      "AccountLink": { "type": ["object", "null"], "properties": { "username": { "type": "string" }, "url": { "type": "string" } } },
      "Player": { "type": "object", "properties": {
        "uid": { "type": "string" }, "name": { "type": ["string", "null"] }, "level": { "type": ["integer", "null"] }, "rank": { "type": ["integer", "null"] },
        "casualRank": { "type": ["integer", "null"] }, "avatarId": { "type": ["integer", "null"] }, "matches": { "type": "integer" },
        "lastPlayedAt": { "type": ["string", "null"], "format": "date-time" },
        "seasons": { "type": "array", "items": { "type": "object", "properties": { "code": { "type": "string" }, "title": { "type": "string" }, "matches": { "type": "integer" }, "current": { "type": "boolean" } } } },
        "account": { "$ref": "#/components/schemas/AccountLink" } } },
      "PlayerMatch": { "type": "object", "properties": {
        "id": { "type": "string" }, "playedAt": { "type": "string", "format": "date-time" }, "map": { "type": "string" }, "mode": { "type": "string" },
        "team": { "type": "integer" }, "score": { "type": "object", "properties": { "team1": { "type": "integer" }, "team2": { "type": "integer" } } },
        "result": { "type": "string", "enum": ["win", "loss", "draw"] }, "kills": { "type": "integer" }, "deaths": { "type": "integer" }, "assists": { "type": "integer" },
        "damage": { "type": "integer" }, "mvp": { "type": "boolean" }, "characters": { "type": "array", "items": { "type": "string" } } } },
      "MatchPlayer": { "type": "object", "properties": {
        "team": { "type": "integer" }, "refused": { "type": "boolean" }, "uid": { "type": ["string", "null"] }, "name": { "type": "string" }, "level": { "type": "integer" },
        "kills": { "type": "integer" }, "deaths": { "type": "integer" }, "assists": { "type": "integer" }, "damage": { "type": "integer" }, "mvp": { "type": "boolean" },
        "characters": { "type": "array", "items": { "type": "string" } }, "account": { "$ref": "#/components/schemas/AccountLink" } } },
      "Match": { "type": "object", "properties": {
        "id": { "type": "string" }, "playedAt": { "type": "string", "format": "date-time" }, "map": { "type": "string" }, "mode": { "type": "string" },
        "score": { "type": "object", "properties": { "team1": { "type": "integer" }, "team2": { "type": "integer" } } }, "winner": { "type": ["integer", "null"] },
        "players": { "type": "array", "items": { "$ref": "#/components/schemas/MatchPlayer" } } } },
      "Profile": { "type": "object", "properties": {
        "username": { "type": "string" }, "url": { "type": "string" }, "uid": { "type": ["string", "null"] }, "avatarUrl": { "type": ["string", "null"] }, "bannerUrl": { "type": ["string", "null"] },
        "bio": { "type": ["string", "null"] }, "level": { "type": "integer" }, "region": { "type": ["string", "null"] }, "country": { "type": ["string", "null"] },
        "badges": { "type": "object", "properties": { "official": { "type": "boolean" }, "verified": { "type": "boolean" }, "premium": { "type": "boolean" }, "creator": { "type": "boolean" } } },
        "joinedAt": { "type": "string", "format": "date-time" } } }
    },
    "responses": {
      "Error": { "description": "Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    }
  },
  "paths": {
    "/key": { "get": { "summary": "The key in use: limits and today's usage", "responses": { "200": { "description": "OK" }, "401": { "$ref": "#/components/responses/Error" } } } },
    "/seasons": { "get": { "summary": "Season schedule, newest first", "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/Season" } } } } } } } } } },
    "/players/{uid}": { "get": { "summary": "A player by in-game UID", "parameters": [{ "name": "uid", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^\\d{5,12}$" } }],
      "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Player" } } } } } }, "403": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } } },
    "/players/{uid}/matches": { "get": { "summary": "A player's matches, newest first", "parameters": [
        { "name": "uid", "in": "path", "required": true, "schema": { "type": "string" } },
        { "name": "season", "in": "query", "schema": { "type": "string" } },
        { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } },
        { "name": "before", "in": "query", "schema": { "type": "string", "format": "date-time" } }],
      "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/PlayerMatch" } }, "next": { "type": ["object", "null"], "properties": { "before": { "type": "string", "format": "date-time" } } } } } } } }, "403": { "$ref": "#/components/responses/Error" } } } },
    "/matches/{id}": { "get": { "summary": "One match with every player", "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
      "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Match" } } } } } }, "404": { "$ref": "#/components/responses/Error" } } } },
    "/profiles/{username}": { "get": { "summary": "A public StrinovaHub profile", "parameters": [{ "name": "username", "in": "path", "required": true, "schema": { "type": "string" } }],
      "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "$ref": "#/components/schemas/Profile" } } } } } }, "403": { "$ref": "#/components/responses/Error" }, "404": { "$ref": "#/components/responses/Error" } } } }
  }
}
