{
  "components" : {
    "schemas" : {
      "ActiveMatchResponse" : {
        "nullable" : false,
        "properties" : {
          "match" : {
            "$ref" : "#/components/schemas/MatchDto"
          }
        },
        "type" : "object"
      },
      "AuthRequest" : {
        "nullable" : false,
        "properties" : {
          "api_key" : {
            "nullable" : false,
            "type" : "string"
          },
          "device_id" : {
            "nullable" : false,
            "type" : "string"
          },
          "nickname" : {
            "nullable" : false,
            "type" : "string"
          },
          "tasks" : {
            "items" : {
              "$ref" : "#/components/schemas/TaskProgress"
            },
            "nullable" : false,
            "type" : "array"
          },
          "user_id" : {
            "nullable" : false,
            "type" : "string"
          }
        },
        "required" : [ "api_key", "device_id", "nickname", "tasks", "user_id" ],
        "type" : "object"
      },
      "AuthResponse" : {
        "nullable" : false,
        "properties" : {
          "session_id" : {
            "nullable" : false,
            "type" : "string"
          }
        },
        "required" : [ "session_id" ],
        "type" : "object"
      },
      "BestResult" : {
        "nullable" : false,
        "properties" : {
          "achieved_at" : {
            "example" : "2026-07-28T14:46:06.143710223Z",
            "format" : "date-time",
            "nullable" : false,
            "type" : "string"
          },
          "score" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          }
        },
        "required" : [ "achieved_at", "score" ],
        "type" : "object"
      },
      "FinishRequest" : {
        "nullable" : false,
        "properties" : {
          "round_scores" : {
            "items" : {
              "format" : "int32",
              "nullable" : false,
              "type" : "integer"
            },
            "nullable" : false,
            "type" : "array"
          }
        },
        "required" : [ "round_scores" ],
        "type" : "object"
      },
      "FinishResponse" : {
        "nullable" : false,
        "properties" : {
          "best_result" : {
            "$ref" : "#/components/schemas/BestResult"
          },
          "is_new_record" : {
            "nullable" : false,
            "type" : "boolean"
          },
          "match_id" : {
            "format" : "int64",
            "nullable" : false,
            "type" : "integer"
          },
          "round_scores" : {
            "items" : {
              "format" : "int32",
              "nullable" : false,
              "type" : "integer"
            },
            "nullable" : false,
            "type" : "array"
          },
          "total_score" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          }
        },
        "required" : [ "best_result", "is_new_record", "match_id", "round_scores", "total_score" ],
        "type" : "object"
      },
      "HealthStatus" : {
        "nullable" : false,
        "properties" : {
          "status" : {
            "nullable" : false,
            "type" : "string"
          }
        },
        "required" : [ "status" ],
        "type" : "object"
      },
      "MatchDto" : {
        "nullable" : false,
        "properties" : {
          "created_at" : {
            "example" : "2026-07-28T14:46:06.143710223Z",
            "format" : "date-time",
            "nullable" : false,
            "type" : "string"
          },
          "deadline" : {
            "example" : "2026-07-28T14:46:06.143710223Z",
            "format" : "date-time",
            "nullable" : false,
            "type" : "string"
          },
          "finished_at" : {
            "example" : "2026-07-28T14:46:06.143710223Z",
            "format" : "date-time",
            "nullable" : true,
            "type" : "string"
          },
          "match_id" : {
            "format" : "int64",
            "nullable" : false,
            "type" : "integer"
          },
          "round_scores" : {
            "items" : {
              "format" : "int32",
              "nullable" : false,
              "type" : "integer"
            },
            "nullable" : true,
            "type" : "array"
          },
          "rounds" : {
            "items" : {
              "$ref" : "#/components/schemas/RoundDto"
            },
            "nullable" : false,
            "type" : "array"
          },
          "status" : {
            "enum" : [ "active", "finished" ],
            "nullable" : false,
            "type" : "string"
          },
          "total_score" : {
            "format" : "int32",
            "nullable" : true,
            "type" : "integer"
          }
        },
        "required" : [ "created_at", "deadline", "match_id", "rounds", "status" ],
        "type" : "object"
      },
      "RoundDto" : {
        "nullable" : false,
        "properties" : {
          "board" : {
            "items" : {
              "nullable" : false,
              "type" : "string"
            },
            "nullable" : false,
            "type" : "array"
          },
          "board_size" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          },
          "duration_seconds" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          },
          "index" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          }
        },
        "required" : [ "board", "board_size", "duration_seconds", "index" ],
        "type" : "object"
      },
      "TaskProgress" : {
        "nullable" : false,
        "properties" : {
          "coins" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          },
          "id" : {
            "nullable" : false,
            "type" : "string"
          }
        },
        "required" : [ "coins", "id" ],
        "type" : "object"
      },
      "UserInfoResponse" : {
        "nullable" : false,
        "properties" : {
          "best_result" : {
            "$ref" : "#/components/schemas/BestResult"
          },
          "coins" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          },
          "energy" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          },
          "energy_max" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          },
          "energy_restore_timer" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          },
          "game_start_energy" : {
            "format" : "int32",
            "nullable" : false,
            "type" : "integer"
          },
          "nickname" : {
            "nullable" : false,
            "type" : "string"
          }
        },
        "required" : [ "coins", "energy", "energy_max", "energy_restore_timer", "game_start_energy", "nickname" ],
        "type" : "object"
      }
    },
    "securitySchemes" : {
      "SessionAuth" : {
        "in" : "header",
        "name" : "Session-ID",
        "type" : "apiKey"
      }
    }
  },
  "info" : {
    "description" : "«Слово за слово» — игровой бэкенд",
    "title" : "AlphaWords API",
    "version" : "dev"
  },
  "openapi" : "3.0.0",
  "paths" : {
    "/health" : {
      "get" : {
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/HealthStatus"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Проверка живости сервиса",
        "tags" : [ "System" ]
      }
    },
    "/auth" : {
      "post" : {
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/AuthRequest"
              }
            }
          }
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/AuthResponse"
                }
              }
            },
            "description" : "OK"
          }
        },
        "summary" : "Создать пользовательскую сессию (межсерверный вызов Alfa-Capital)",
        "tags" : [ "Auth" ]
      }
    },
    "/user/info" : {
      "get" : {
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/UserInfoResponse"
                }
              }
            },
            "description" : "OK"
          }
        },
        "security" : [ {
          "SessionAuth" : [ ]
        } ],
        "summary" : "Данные главного экрана игрока",
        "tags" : [ "User" ]
      }
    },
    "/user/matches" : {
      "post" : {
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/MatchDto"
                }
              }
            },
            "description" : "OK"
          }
        },
        "security" : [ {
          "SessionAuth" : [ ]
        } ],
        "summary" : "Старт партии — списывает энергию, отдаёт 3 тестовых раунда",
        "tags" : [ "Match" ]
      },
      "get" : {
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ActiveMatchResponse"
                }
              }
            },
            "description" : "OK"
          }
        },
        "security" : [ {
          "SessionAuth" : [ ]
        } ],
        "summary" : "Активная партия игрока или её отсутствие",
        "tags" : [ "Match" ]
      }
    },
    "/user/matches/{id}" : {
      "get" : {
        "parameters" : [ {
          "deprecated" : false,
          "description" : "match id",
          "explode" : false,
          "in" : "path",
          "name" : "id",
          "required" : true,
          "schema" : {
            "format" : "int64",
            "nullable" : false,
            "type" : "integer"
          },
          "style" : "simple"
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/MatchDto"
                }
              }
            },
            "description" : "OK"
          }
        },
        "security" : [ {
          "SessionAuth" : [ ]
        } ],
        "summary" : "Загрузка партии по id",
        "tags" : [ "Match" ]
      }
    },
    "/user/matches/{id}/finish" : {
      "post" : {
        "parameters" : [ {
          "deprecated" : false,
          "description" : "match id",
          "explode" : false,
          "in" : "path",
          "name" : "id",
          "required" : true,
          "schema" : {
            "format" : "int64",
            "nullable" : false,
            "type" : "integer"
          },
          "style" : "simple"
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/FinishRequest"
              }
            }
          }
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/FinishResponse"
                }
              }
            },
            "description" : "OK"
          }
        },
        "security" : [ {
          "SessionAuth" : [ ]
        } ],
        "summary" : "Завершение партии — идемпотентно, обновляет рекорд",
        "tags" : [ "Match" ]
      }
    }
  },
  "servers" : [ {
    "description" : "Local",
    "url" : "http://localhost:8080"
  } ],
  "tags" : [ {
    "description" : "Служебные",
    "name" : "System"
  }, {
    "description" : "Авторизация",
    "name" : "Auth"
  }, {
    "description" : "Пользователь",
    "name" : "User"
  }, {
    "description" : "Партия",
    "name" : "Match"
  } ]
}