{
  "openapi": "3.0.1",
  "info": {
    "title": "Pw Modules API",
    "version": "v1"
  },
  "paths": {
    "/api/auth/password": {
      "post": {
        "tags": [
          "ChangePasswordEndpoint"
        ],
        "operationId": "ChangePassword",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/telegram/consume": {
      "post": {
        "tags": [
          "ConsumeTelegramStateEndpoint"
        ],
        "summary": "Потребляет state и привязывает Telegram к пользователю",
        "description": "Для Telegram-бота. Требуется заголовок X-Bot-Token. Тело: { state, telegramId, telegramUsername }.",
        "operationId": "ConsumeTelegramState",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConsumeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/modules": {
      "post": {
        "tags": [
          "CreateModuleEndpoint"
        ],
        "operationId": "CreateModule",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateModuleRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "get": {
        "tags": [
          "SearchModulesEndpoint"
        ],
        "operationId": "SearchModules",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          },
          {
            "name": "sinceDays",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/modules/{id}": {
      "delete": {
        "tags": [
          "DeleteModuleEndpoint"
        ],
        "operationId": "DeleteModule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "get": {
        "tags": [
          "GetModuleEndpoint"
        ],
        "summary": "Получает информацию о модуле",
        "description": "Требуется заголовок X-Api-Token.",
        "operationId": "GetModule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "put": {
        "tags": [
          "UpdateModuleEndpoint"
        ],
        "operationId": "UpdateModule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateModuleRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/exchange": {
      "post": {
        "tags": [
          "ExchangeBearerEndpoint"
        ],
        "operationId": "ExchangeBearerForSession",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/telegram/link": {
      "post": {
        "tags": [
          "GenerateTelegramLinkEndpoint"
        ],
        "summary": "Генерирует ссылку для Telegram-бота с предзаполненным state",
        "description": "Требуется заголовок X-Auth-Token. Возвращает deep-link на бота вида https://t.me/<bot>?start=<state> вместе с самим state и временем истечения.",
        "operationId": "GenerateTelegramLink",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/telegram/state": {
      "post": {
        "tags": [
          "GenerateTelegramStateEndpoint"
        ],
        "summary": "Генерирует state для привязки аккаунта к Telegram-боту",
        "description": "Требуется заголовок X-Auth-Token. Возвращает короткоживущий state, по которому бот сможет связать аккаунт пользователя.",
        "operationId": "GenerateTelegramState",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/modules/{id}/run": {
      "post": {
        "tags": [
          "IncrementRunEndpoint"
        ],
        "operationId": "IncrementRun",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/modules/{id}/install": {
      "post": {
        "tags": [
          "InstallModuleEndpoint"
        ],
        "operationId": "InstallModule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "userId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "delete": {
        "tags": [
          "UninstallModuleEndpoint"
        ],
        "operationId": "UninstallModule",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "userId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/modules/installed": {
      "get": {
        "tags": [
          "InstalledModulesEndpoint"
        ],
        "operationId": "GetInstalledModules",
        "parameters": [
          {
            "name": "userId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/login": {
      "post": {
        "tags": [
          "LoginEndpoint"
        ],
        "operationId": "Login",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/login": {
      "get": {
        "tags": [
          "LoginEndpoints"
        ],
        "operationId": "LoginUi",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "post": {
        "tags": [
          "LoginEndpoints"
        ],
        "operationId": "LoginUiPost",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginUiRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/login/register": {
      "post": {
        "tags": [
          "LoginEndpoints"
        ],
        "operationId": "LoginUiRegister",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginUiRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/app/manifest": {
      "get": {
        "tags": [
          "ManifestEndpoint"
        ],
        "operationId": "GetAppManifest",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/me": {
      "get": {
        "tags": [
          "MeEndpoint"
        ],
        "operationId": "Me",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/connect/authorize": {
      "get": {
        "tags": [
          "OidcEndpoints"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "post": {
        "tags": [
          "OidcEndpoints"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/connect/logout": {
      "get": {
        "tags": [
          "OidcEndpoints"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "post": {
        "tags": [
          "OidcEndpoints"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/connect/token": {
      "post": {
        "tags": [
          "OidcEndpoints"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/register": {
      "post": {
        "tags": [
          "RegisterEndpoint"
        ],
        "operationId": "Register",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/password/reset": {
      "post": {
        "tags": [
          "ResetPasswordEndpoint"
        ],
        "summary": "Сброс пароля текущего пользователя",
        "description": "Требуется X-Auth-Token. Если Telegram привязан — пароль отправляется в Telegram и не возвращается в теле ответа.",
        "operationId": "ResetPassword",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResetPasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/telegram/send": {
      "post": {
        "tags": [
          "SendMessageEndpoint"
        ],
        "description": "Отправить сообщение себе в Telegram. Требуется X-Auth-Token. Пользователь должен быть привязан к Telegram.",
        "operationId": "Auth_Telegram_Send",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessageRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/app/stats": {
      "get": {
        "tags": [
          "StatsEndpoint"
        ],
        "summary": "Возвращает статистику по пользователям и модулям",
        "description": "Количество активных пользователей (по незавершенным сессиям), количество модулей и общее количество запусков модулей",
        "operationId": "GetAppStats",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/telegram/widget": {
      "post": {
        "tags": [
          "TelegramWidgetLoginEndpoint"
        ],
        "operationId": "TelegramWidgetLogin",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WidgetPayload"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/telegram/unlink": {
      "post": {
        "tags": [
          "UnlinkTelegramEndpoint"
        ],
        "summary": "Отвязывает Telegram от аккаунта пользователя",
        "description": "Требуется заголовок X-Auth-Token. Очищает поля TelegramId/TelegramUsername/TelegramLinkedAt у пользователя и возвращает обновлённого пользователя.",
        "operationId": "UnlinkTelegram",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/auth/username": {
      "post": {
        "tags": [
          "UpdateUsernameEndpoint"
        ],
        "operationId": "UpdateUsername",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateUsernameRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/app/versions": {
      "post": {
        "tags": [
          "UploadVersionEndpoint"
        ],
        "operationId": "UploadAppVersion",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ChangePasswordRequest": {
        "type": "object",
        "properties": {
          "currentPassword": {
            "type": "string",
            "nullable": true
          },
          "newPassword": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ConsumeRequest": {
        "type": "object",
        "properties": {
          "state": {
            "type": "string",
            "nullable": true
          },
          "telegramId": {
            "type": "integer",
            "format": "int64"
          },
          "telegramUsername": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "CreateModuleRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "version": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "script": {
            "type": "string",
            "nullable": true
          },
          "inputs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InputDefinitionDto"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "InputDefinitionDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "type": {
            "type": "string",
            "nullable": true
          },
          "default": {
            "type": "string",
            "nullable": true
          },
          "required": {
            "type": "boolean"
          },
          "options": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "LoginRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "nullable": true
          },
          "password": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "LoginUiRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "nullable": true
          },
          "password": {
            "type": "string",
            "nullable": true
          },
          "returnUrl": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "RegisterRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "nullable": true
          },
          "password": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ResetPasswordRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "SendMessageRequest": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "StatsResponse": {
        "type": "object",
        "properties": {
          "activeUsers": {
            "type": "integer",
            "format": "int32"
          },
          "modules": {
            "type": "integer",
            "format": "int32"
          },
          "moduleRuns": {
            "type": "integer",
            "format": "int64"
          }
        },
        "additionalProperties": false
      },
      "UpdateModuleRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "version": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "script": {
            "type": "string",
            "nullable": true
          },
          "inputs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InputDefinitionDto"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "UpdateUsernameRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "WidgetPayload": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "first_name": {
            "type": "string",
            "nullable": true
          },
          "last_name": {
            "type": "string",
            "nullable": true
          },
          "username": {
            "type": "string",
            "nullable": true
          },
          "photo_url": {
            "type": "string",
            "nullable": true
          },
          "auth_date": {
            "type": "integer",
            "format": "int64"
          },
          "hash": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      }
    }
  }
}