{
  "openapi": "3.0.3",
  "info": {
    "title": "SHost Panel API",
    "version": "2.2.0",
    "description": "Автоматизация собственной панели SHost. Запросы идут на адрес конкретной панели; apihost.silentshop.shop содержит документацию. HTTPS обязателен для передачи секретов."
  },
  "servers": [
    {
      "url": "https://YOUR_PANEL_HOST:YOUR_PANEL_PORT",
      "description": "Замените адресом вашей панели из раздела API"
    }
  ],
  "security": [
    {
      "panelKey": []
    }
  ],
  "tags": [
    {
      "name": "Быстрый старт"
    },
    {
      "name": "Сервер"
    },
    {
      "name": "Инбаунды"
    },
    {
      "name": "Клиенты"
    },
    {
      "name": "Подписки"
    },
    {
      "name": "Журнал"
    },
    {
      "name": "API-ключи"
    },
    {
      "name": "Аккаунт"
    }
  ],
  "paths": {
    "/api/v1/account": {
      "get": {
        "summary": "Проверить API-ключ",
        "tags": [
          "Быстрый старт"
        ],
        "operationId": "get__api_v1_account",
        "description": "",
        "x-scope": "read",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "example": {
                  "username": "admin",
                  "csrf": "",
                  "version": "2.2.0"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/servers": {
      "get": {
        "summary": "Получить сведения о панели",
        "tags": [
          "Сервер"
        ],
        "operationId": "get__api_v1_servers",
        "description": "Возвращается массив с одной записью этой панели. Здесь находятся выделенные порты inbound_ports.",
        "x-scope": "read",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Server"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/servers/{id}": {
      "get": {
        "summary": "Получить сервер по ID",
        "tags": [
          "Сервер"
        ],
        "operationId": "get__api_v1_servers__id_",
        "description": "",
        "x-scope": "read",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Server"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Идентификатор из ответа списка"
        }
      ]
    },
    "/api/v1/metrics": {
      "get": {
        "summary": "Получить текущие метрики",
        "tags": [
          "Сервер"
        ],
        "operationId": "get__api_v1_metrics",
        "description": "",
        "x-scope": "read",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Metrics"
                },
                "example": {
                  "timestamp": 1793188800,
                  "xray_running": true,
                  "configuration_error": false,
                  "configured_clients": 12,
                  "active_inbounds": 2
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/inbounds": {
      "get": {
        "summary": "Получить инбаунды",
        "tags": [
          "Инбаунды"
        ],
        "operationId": "get__api_v1_inbounds",
        "description": "",
        "x-scope": "read",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Inbound"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Создать инбаунд",
        "tags": [
          "Инбаунды"
        ],
        "operationId": "post__api_v1_inbounds",
        "description": "Замените port свободным портом из inbound_ports вашей панели. Reality-ключи создаются автоматически. Для Hysteria 2 используйте protocol=hysteria, network=hysteria, security=tls и SNI действующего сертификата. Доступны только выделенные порты; превышение квоты или занятый порт дают 400.",
        "x-scope": "write",
        "responses": {
          "201": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Inbound"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InboundCreate"
              },
              "example": {
                "name": "Основное подключение",
                "protocol": "vless",
                "port": 21042,
                "network": "tcp",
                "security": "reality",
                "dest": "www.yahoo.com:443",
                "server_names": [
                  "www.yahoo.com"
                ],
                "flow": "xtls-rprx-vision"
              }
            }
          }
        }
      }
    },
    "/api/v1/inbounds/{id}": {
      "delete": {
        "summary": "Удалить инбаунд",
        "tags": [
          "Инбаунды"
        ],
        "operationId": "delete__api_v1_inbounds__id_",
        "description": "Инбаунд перестаёт принимать подключения. Сами записи клиентов сохраняются.",
        "x-scope": "write",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "success": true,
                  "message": "inbound deleted"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Идентификатор из ответа списка"
        }
      ]
    },
    "/api/v1/xray/new-keys": {
      "get": {
        "summary": "Создать пару ключей Reality",
        "tags": [
          "Инбаунды"
        ],
        "operationId": "get__api_v1_xray_new_keys",
        "description": "Генерирует новую пару X25519 и short_id. Действующие инбаунды не изменяются.",
        "x-scope": "write",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RealityKeys"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/clients": {
      "get": {
        "summary": "Получить клиентов и ссылки",
        "tags": [
          "Клиенты"
        ],
        "operationId": "get__api_v1_clients",
        "description": "Ответ содержит ключи подключения и ссылки подписок: храните его как секрет. devices не раскрывает credential и hwid_hash. При max_devices > 0 используйте sub_url в Happ с X-HWID.",
        "x-scope": "read",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Client"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Создать клиента",
        "tags": [
          "Клиенты"
        ],
        "operationId": "post__api_v1_clients",
        "description": "Замените inbound_ids идентификаторами из GET /api/v1/inbounds. Если список не указан, назначаются все текущие инбаунды. Для ограничений на старых Trojan/Shadowsocks с общим паролем сначала создайте новый инбаунд с индивидуальными ключами. До 5000 клиентов на панель.",
        "x-scope": "write",
        "responses": {
          "201": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientCreate"
              },
              "example": {
                "name": "Клиент из бота",
                "duration_days": 30,
                "inbound_ids": [
                  "inb-example"
                ],
                "traffic_gb": 100,
                "max_devices": 3
              }
            }
          }
        }
      }
    },
    "/api/v1/clients/{id}": {
      "delete": {
        "summary": "Удалить клиента",
        "tags": [
          "Клиенты"
        ],
        "operationId": "delete__api_v1_clients__id_",
        "description": "",
        "x-scope": "write",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "success": true,
                  "message": "client deleted"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Идентификатор из ответа списка"
        }
      ]
    },
    "/api/v1/clients/{id}/limits": {
      "patch": {
        "summary": "Изменить лимиты клиента",
        "tags": [
          "Клиенты"
        ],
        "operationId": "patch__api_v1_clients__id__limits",
        "description": "Передавайте оба поля: отсутствующее поле в текущем API равно 0. Нельзя уменьшить max_devices ниже числа зарегистрированных устройств: сначала отзовите лишние устройства. 0 — без ограничений.",
        "x-scope": "write",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OK"
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Limits"
              },
              "example": {
                "traffic_gb": 200,
                "max_devices": 5
              }
            }
          }
        }
      },
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Идентификатор из ответа списка"
        }
      ]
    },
    "/api/v1/clients/{id}/reset-traffic": {
      "post": {
        "summary": "Сбросить расход трафика",
        "tags": [
          "Клиенты"
        ],
        "operationId": "post__api_v1_clients__id__reset_traffic",
        "description": "Обнуляет upload_bytes и download_bytes. При исчерпанной квоте доступ восстанавливается, если срок ещё действует.",
        "x-scope": "write",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OK"
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Идентификатор из ответа списка"
        }
      ]
    },
    "/api/v1/clients/{id}/devices/{deviceId}": {
      "delete": {
        "summary": "Отключить устройство",
        "tags": [
          "Клиенты"
        ],
        "operationId": "delete__api_v1_clients__id__devices__deviceId_",
        "description": "Удаляет зарегистрированное устройство и его ключ из Xray. Повторный импорт подписки может зарегистрировать его заново при наличии свободного места.",
        "x-scope": "write",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OK"
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Идентификатор из ответа списка"
        },
        {
          "name": "deviceId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Идентификатор устройства из devices"
        }
      ]
    },
    "/api/v1/subscription/settings": {
      "get": {
        "summary": "Получить настройки подписки",
        "tags": [
          "Подписки"
        ],
        "operationId": "get__api_v1_subscription_settings",
        "description": "",
        "x-scope": "read",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subscription"
                },
                "example": {
                  "title": "МОЙ СЕРВАК",
                  "description": "Личный доступ",
                  "update_interval": 24
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Сохранить настройки подписки",
        "tags": [
          "Подписки"
        ],
        "operationId": "post__api_v1_subscription_settings",
        "description": "Полностью заменяет параметры подписки. Название группы передаётся в Profile-Title, имя узла задаётся инбаундом.",
        "x-scope": "write",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "settings": {
                      "$ref": "#/components/schemas/Subscription"
                    }
                  }
                },
                "example": {
                  "status": "ok",
                  "settings": {
                    "title": "МОЙ СЕРВАК",
                    "description": "Личный доступ",
                    "update_interval": 24
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Subscription"
              },
              "example": {
                "title": "МОЙ СЕРВАК",
                "description": "Личный доступ",
                "update_interval": 24
              }
            }
          }
        }
      }
    },
    "/api/v1/logs": {
      "get": {
        "summary": "Получить журнал",
        "tags": [
          "Журнал"
        ],
        "operationId": "get__api_v1_logs",
        "description": "Последние 100 записей, новые первыми. Не содержит API-секретов.",
        "x-scope": "read",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Log"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys": {
      "get": {
        "summary": "Получить список API-ключей",
        "tags": [
          "API-ключи"
        ],
        "operationId": "get__api_v1_api_keys",
        "description": "Возвращаются метаданные, без полного секрета и его хеша.",
        "x-scope": "admin",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/APIKey"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Создать API-ключ",
        "tags": [
          "API-ключи"
        ],
        "operationId": "post__api_v1_api_keys",
        "description": "Полный ключ виден один раз. write включает read. Нельзя выдать больше прав или более долгий срок, чем у текущего ключа. Не больше 20 действующих ключей. Без Bearer, через интерфейс, доступен выбор любых прав.",
        "x-scope": "admin",
        "responses": {
          "201": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIKeyCreated"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/APIKeyCreate"
              },
              "example": {
                "name": "Бот продаж",
                "scopes": [
                  "write"
                ],
                "expires_in_days": 30
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{id}": {
      "delete": {
        "summary": "Отозвать API-ключ",
        "tags": [
          "API-ключи"
        ],
        "operationId": "delete__api_v1_api_keys__id_",
        "description": "Новые запросы отклоняются сразу. Его открытые WebSocket-соединения закрываются в течение секунды.",
        "x-scope": "admin",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OK"
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Идентификатор из ответа списка"
        }
      ]
    },
    "/api/v1/account/password": {
      "post": {
        "summary": "Изменить пароль панели",
        "tags": [
          "Аккаунт"
        ],
        "operationId": "post__api_v1_account_password",
        "description": "Требует действующий пароль даже при использовании ключа. Завершает сессии браузера. API-ключи отзываются отдельно.",
        "x-scope": "admin",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OK"
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Password"
              },
              "example": {
                "current": "CURRENT_PASSWORD",
                "password": "NEW_PASSWORD_AT_LEAST_10_BYTES"
              }
            }
          }
        }
      }
    },
    "/api/v1/openapi.json": {
      "get": {
        "summary": "Скачать контракт OpenAPI",
        "tags": [
          "Быстрый старт"
        ],
        "operationId": "get__api_v1_openapi_json",
        "description": "Тот же контракт, на котором построена эта документация. Публичная копия доступна на сайте документации.",
        "x-scope": "read",
        "responses": {
          "200": {
            "description": "Успешный ответ",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Некорректные параметры",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Неверный, просроченный или отозванный ключ",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Недостаточно прав",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Объект или маршрут не найден",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "HTTP-метод не поддерживается",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Конфигурация Xray не принята, изменения отменены",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Превышена частота запросов",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Секунды до следующего запроса",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "500": {
            "description": "Не удалось сохранить данные",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "panelKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "shost_…",
        "description": "Ключ создаётся в разделе API конкретной панели"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      },
      "OK": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ]
      },
      "Inbound": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "protocol": {
            "type": "string",
            "enum": [
              "vless",
              "vmess",
              "trojan",
              "shadowsocks",
              "hysteria"
            ]
          },
          "port": {
            "type": "integer",
            "description": "Только выделенный и свободный порт из inbound_ports",
            "minimum": 1,
            "maximum": 65535
          },
          "network": {
            "type": "string",
            "enum": [
              "tcp",
              "ws",
              "grpc",
              "httpupgrade",
              "hysteria"
            ]
          },
          "security": {
            "type": "string",
            "enum": [
              "none",
              "tls",
              "reality"
            ]
          },
          "flow": {
            "type": "string",
            "description": "Для VLESS TCP Reality обычно xtls-rprx-vision"
          },
          "dest": {
            "type": "string",
            "description": "Reality destination, например www.yahoo.com:443"
          },
          "server_names": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string",
              "description": "SNI"
            }
          },
          "private_key": {
            "type": "string",
            "description": "Для Reality генерируется, если не задан"
          },
          "public_key": {
            "type": "string"
          },
          "short_ids": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            }
          },
          "spider_x": {
            "type": "string"
          },
          "fingerprint": {
            "type": "string"
          },
          "ws_path": {
            "type": "string"
          },
          "ws_host": {
            "type": "string"
          },
          "grpc_service": {
            "type": "string"
          },
          "http_path": {
            "type": "string"
          },
          "http_host": {
            "type": "string"
          },
          "method": {
            "type": "string",
            "enum": [
              "",
              "aes-128-gcm",
              "aes-256-gcm",
              "chacha20-poly1305"
            ]
          },
          "password": {
            "type": "string",
            "description": "Новые Trojan и Shadowsocks используют индивидуальный ключ клиента"
          },
          "per_client": {
            "type": "boolean"
          },
          "sniffing": {
            "type": "boolean"
          },
          "status": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "InboundCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "protocol": {
            "type": "string",
            "enum": [
              "vless",
              "vmess",
              "trojan",
              "shadowsocks",
              "hysteria"
            ]
          },
          "port": {
            "type": "integer",
            "description": "Только выделенный и свободный порт из inbound_ports",
            "minimum": 1,
            "maximum": 65535
          },
          "network": {
            "type": "string",
            "enum": [
              "tcp",
              "ws",
              "grpc",
              "httpupgrade",
              "hysteria"
            ]
          },
          "security": {
            "type": "string",
            "enum": [
              "none",
              "tls",
              "reality"
            ]
          },
          "flow": {
            "type": "string",
            "description": "Для VLESS TCP Reality обычно xtls-rprx-vision"
          },
          "dest": {
            "type": "string",
            "description": "Reality destination, например www.yahoo.com:443"
          },
          "server_names": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string",
              "description": "SNI"
            }
          },
          "private_key": {
            "type": "string",
            "description": "Для Reality генерируется, если не задан"
          },
          "public_key": {
            "type": "string"
          },
          "short_ids": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            }
          },
          "spider_x": {
            "type": "string"
          },
          "fingerprint": {
            "type": "string"
          },
          "ws_path": {
            "type": "string"
          },
          "ws_host": {
            "type": "string"
          },
          "grpc_service": {
            "type": "string"
          },
          "http_path": {
            "type": "string"
          },
          "http_host": {
            "type": "string"
          },
          "method": {
            "type": "string",
            "enum": [
              "",
              "aes-128-gcm",
              "aes-256-gcm",
              "chacha20-poly1305"
            ]
          },
          "password": {
            "type": "string",
            "description": "Новые Trojan и Shadowsocks используют индивидуальный ключ клиента"
          }
        },
        "required": [
          "name",
          "protocol",
          "port"
        ]
      },
      "ClientCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "duration_days": {
            "type": "integer",
            "description": "Срок доступа в днях",
            "minimum": 1,
            "maximum": 3650
          },
          "inbound_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "Если не заданы, используются все текущие инбаунды"
            }
          },
          "inbound_id": {
            "type": "string",
            "description": "Совместимое поле для одного инбаунда; предпочитайте inbound_ids"
          },
          "traffic_gb": {
            "type": "integer",
            "description": "Загрузка + отдача. 1 ГБ = 1073741824 байта. 0 — без ограничений",
            "minimum": 0,
            "maximum": 1000000
          },
          "max_devices": {
            "type": "integer",
            "description": "Число зарегистрированных HWID. 0 — без ограничений",
            "minimum": 0,
            "maximum": 100
          }
        },
        "required": [
          "name",
          "duration_days"
        ]
      },
      "Limits": {
        "type": "object",
        "properties": {
          "traffic_gb": {
            "type": "integer",
            "description": "Загрузка + отдача. 1 ГБ = 1073741824 байта. 0 — без ограничений",
            "minimum": 0,
            "maximum": 1000000
          },
          "max_devices": {
            "type": "integer",
            "description": "Число зарегистрированных HWID. 0 — без ограничений",
            "minimum": 0,
            "maximum": 100
          }
        },
        "required": [
          "traffic_gb",
          "max_devices"
        ]
      },
      "Device": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_seen": {
            "type": "string",
            "format": "date-time"
          },
          "credential": {
            "type": "string",
            "description": "Пустая строка в ответе списка"
          },
          "hwid_hash": {
            "type": "string",
            "description": "Пустая строка в ответе списка"
          }
        }
      },
      "Client": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "uuid": {
            "type": "string"
          },
          "inbound_id": {
            "type": "string"
          },
          "inbound_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "protocol": {
            "type": "string"
          },
          "port": {
            "type": "integer"
          },
          "link": {
            "type": "string",
            "description": "Пустая строка при включённом лимите устройств"
          },
          "sub_url": {
            "type": "string"
          },
          "sub_json_url": {
            "type": "string"
          },
          "expire_days": {
            "type": "integer"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string"
          },
          "upload_bytes": {
            "type": "integer"
          },
          "download_bytes": {
            "type": "integer"
          },
          "devices": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/Device"
            }
          },
          "traffic_gb": {
            "type": "integer",
            "description": "Загрузка + отдача. 1 ГБ = 1073741824 байта. 0 — без ограничений",
            "minimum": 0,
            "maximum": 1000000
          },
          "max_devices": {
            "type": "integer",
            "description": "Число зарегистрированных HWID. 0 — без ограничений",
            "minimum": 0,
            "maximum": 100
          }
        }
      },
      "Subscription": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "maxLength": 200
          },
          "update_interval": {
            "type": "integer",
            "description": "Интервал обновления, часы",
            "minimum": 1,
            "maximum": 168
          }
        },
        "required": [
          "title",
          "description",
          "update_interval"
        ]
      },
      "Server": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "domain": {
            "type": "string"
          },
          "host_ip": {
            "type": "string"
          },
          "web_port": {
            "type": "integer"
          },
          "sub_port": {
            "type": "integer"
          },
          "inbound_port_1": {
            "type": "integer"
          },
          "inbound_port_2": {
            "type": "integer"
          },
          "inbound_port_3": {
            "type": "integer"
          },
          "inbound_ports": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "cpu_cores": {
            "type": "number"
          },
          "ram_mb": {
            "type": "integer"
          },
          "disk_gb": {
            "type": "integer"
          },
          "bandwidth_mbps": {
            "type": "integer"
          },
          "admin_user": {
            "type": "string"
          },
          "client_count": {
            "type": "integer"
          },
          "inbound_count": {
            "type": "integer"
          },
          "sub_url": {
            "type": "string"
          }
        }
      },
      "APIKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string",
            "description": "Скрытый префикс, не полный ключ"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "write",
                "console",
                "admin"
              ]
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_used_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "revoked_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "APIKeyCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "write",
                "console",
                "admin"
              ]
            }
          },
          "expires_in_days": {
            "type": "integer",
            "enum": [
              0,
              30,
              90,
              365
            ],
            "default": 90,
            "description": "Укажите явно. 0 — без срока"
          }
        },
        "required": [
          "name",
          "scopes",
          "expires_in_days"
        ]
      },
      "APIKeyCreated": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "Полный секрет, показывается только в этом ответе"
          },
          "api_key": {
            "$ref": "#/components/schemas/APIKey"
          }
        },
        "required": [
          "key",
          "api_key"
        ]
      },
      "Account": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string"
          },
          "csrf": {
            "type": "string",
            "description": "Для Bearer пустая строка"
          },
          "version": {
            "type": "string"
          },
          "api_key": {
            "$ref": "#/components/schemas/APIKey"
          }
        }
      },
      "RealityKeys": {
        "type": "object",
        "properties": {
          "private_key": {
            "type": "string"
          },
          "public_key": {
            "type": "string"
          },
          "short_id": {
            "type": "string"
          }
        }
      },
      "Log": {
        "type": "object",
        "properties": {
          "time": {
            "type": "string",
            "description": "DD.MM.YYYY HH:MM"
          },
          "type": {
            "type": "string"
          },
          "user": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "ip": {
            "type": "string"
          }
        }
      },
      "Password": {
        "type": "object",
        "properties": {
          "current": {
            "type": "string",
            "format": "password"
          },
          "password": {
            "type": "string",
            "format": "password",
            "description": "От 10 до 72 байт"
          }
        },
        "required": [
          "current",
          "password"
        ]
      },
      "Deleted": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Metrics": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "integer"
          },
          "xray_running": {
            "type": "boolean"
          },
          "configuration_error": {
            "type": "boolean"
          },
          "cpu_usage": {
            "type": "number",
            "nullable": true
          },
          "ram_usage_mb": {
            "type": "number",
            "nullable": true
          },
          "ram_total_mb": {
            "type": "integer"
          },
          "disk_usage_gb": {
            "type": "number",
            "nullable": true
          },
          "disk_total_gb": {
            "type": "integer"
          },
          "net_rx_kbps": {
            "type": "number"
          },
          "net_tx_kbps": {
            "type": "number"
          },
          "total_rx_bytes": {
            "type": "integer"
          },
          "total_tx_bytes": {
            "type": "integer"
          },
          "active_inbounds": {
            "type": "integer"
          },
          "configured_clients": {
            "type": "integer"
          }
        }
      }
    }
  }
}
