{
    "openapi": "3.1.0",
    "info": {
        "title": "vvall Files API",
        "version": "1.2.0",
        "description": "Управление статичными файлами. Bearer-токен всегда даёт чтение и запись в заданных сайтах. Аккаунты/сайты под блокировкой доступны только для чтения; после 30 дней блокировки аккаунта доступ закрывается. Не передавайте токен в URL. Пути UTF-8, без начального /, обратных слешей, точечных/служебных компонентов. Регистр родителей должен точно совпадать. Лимит файла 25 МиБ; текстовый редактор панели 2 МиБ; ZIP до 2000 записей, вся операция атомарна. CORS не включён. Ошибка: {\"error\":{\"message\":\"…\",\"status\":403}}. Публичные ключи просмотра не ограничивают Bearer API. Токен также управляет правилами доступа через /sites/{id}/access в пределах разрешённых сайтов."
    },
    "servers": [
        {
            "url": "https://vvall.ru/api/v1"
        }
    ],
    "security": [
        {
            "bearerAuth": []
        }
    ],
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer"
            }
        },
        "schemas": {
            "AccessWrite": {
                "type": "object",
                "required": [
                    "mode"
                ],
                "properties": {
                    "path": {
                        "type": "string",
                        "default": "",
                        "description": "Пусто: корень сайта; иначе точный относительный путь существующего файла/папки."
                    },
                    "mode": {
                        "type": "string",
                        "enum": [
                            "inherit",
                            "public",
                            "key"
                        ]
                    },
                    "key": {
                        "type": "string",
                        "writeOnly": true,
                        "minLength": 12,
                        "maxLength": 256,
                        "description": "Новый ключ. При существующем собственном key отсутствие значения сохраняет ключ."
                    },
                    "generate": {
                        "type": "boolean",
                        "description": "Создать случайный ключ и вернуть generated_key только в этом ответе."
                    },
                    "revoke": {
                        "type": "boolean",
                        "description": "Отозвать выданные посетителям разрешения, оставив ключ."
                    }
                }
            },
            "AccessInfo": {
                "type": "object",
                "required": [
                    "path",
                    "mode",
                    "effective",
                    "inherited",
                    "from_path",
                    "has_key"
                ],
                "properties": {
                    "path": {
                        "type": "string"
                    },
                    "mode": {
                        "type": "string",
                        "enum": [
                            "inherit",
                            "public",
                            "key"
                        ]
                    },
                    "effective": {
                        "type": "string",
                        "enum": [
                            "public",
                            "key"
                        ]
                    },
                    "inherited": {
                        "type": "boolean"
                    },
                    "from_path": {
                        "type": "string"
                    },
                    "has_key": {
                        "type": "boolean"
                    },
                    "parent": {
                        "description": "Безопасные метаданные родительского правила; null для корня.",
                        "type": [
                            "object",
                            "null"
                        ]
                    }
                }
            },
            "AccessResult": {
                "type": "object",
                "properties": {
                    "access": {
                        "$ref": "#/components/schemas/AccessInfo"
                    },
                    "generated_key": {
                        "type": "string",
                        "description": "Только после generate:true; никогда при обычном чтении."
                    }
                }
            }
        }
    },
    "paths": {
        "/sites": {
            "get": {
                "summary": "Сайты, доступные этому токену. Создание и удаление сайтов через API отсутствуют.",
                "responses": {
                    "200": {
                        "description": "Успех",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "sites"
                                    ],
                                    "properties": {
                                        "sites": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "required": [
                                                    "id",
                                                    "slug",
                                                    "title",
                                                    "url",
                                                    "blocked_at"
                                                ],
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "slug": {
                                                        "type": "string"
                                                    },
                                                    "title": {
                                                        "type": "string"
                                                    },
                                                    "url": {
                                                        "type": "string",
                                                        "format": "uri",
                                                        "description": "Канонический HTTPS-адрес корня сайта; завершается слешем. Не гарантирует публичность при блокировке."
                                                    },
                                                    "blocked_at": {
                                                        "type": [
                                                            "integer",
                                                            "null"
                                                        ]
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "sites": [
                                        {
                                            "id": 1,
                                            "slug": "example",
                                            "title": "Мой сайт",
                                            "blocked_at": null,
                                            "url": "https://example.vvall.ru/"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/files": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                },
                {
                    "name": "path",
                    "in": "query",
                    "required": false,
                    "schema": {
                        "type": "string"
                    },
                    "description": "Относительный путь от корня сайта; пустая строка — корень."
                }
            ],
            "get": {
                "summary": "Содержимое папки; карантин отмечен state=quarantine.",
                "responses": {
                    "200": {
                        "description": "Успех",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "entries"
                                    ],
                                    "properties": {
                                        "entries": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "required": [
                                                    "id",
                                                    "site_id",
                                                    "path",
                                                    "kind",
                                                    "size",
                                                    "state",
                                                    "etag"
                                                ],
                                                "properties": {
                                                    "id": {
                                                        "type": "integer"
                                                    },
                                                    "site_id": {
                                                        "type": "integer"
                                                    },
                                                    "path": {
                                                        "type": "string"
                                                    },
                                                    "kind": {
                                                        "type": "string",
                                                        "enum": [
                                                            "file",
                                                            "dir"
                                                        ]
                                                    },
                                                    "size": {
                                                        "type": "integer"
                                                    },
                                                    "state": {
                                                        "type": "string",
                                                        "enum": [
                                                            "live",
                                                            "quarantine",
                                                            "trash"
                                                        ]
                                                    },
                                                    "etag": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ]
                                                    }
                                                },
                                                "additionalProperties": true
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "entries": [
                                        {
                                            "id": 42,
                                            "site_id": 1,
                                            "path": "pages/index.html",
                                            "kind": "file",
                                            "size": 34,
                                            "state": "live",
                                            "etag": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                                            "updated_at": 1700000000
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/file": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                },
                {
                    "name": "path",
                    "in": "query",
                    "required": false,
                    "schema": {
                        "type": "string"
                    },
                    "description": "Относительный путь от корня сайта; пустая строка — корень."
                },
                {
                    "name": "overwrite",
                    "in": "query",
                    "schema": {
                        "type": "string",
                        "enum": [
                            "1"
                        ]
                    }
                },
                {
                    "name": "If-Match",
                    "in": "header",
                    "schema": {
                        "type": "string"
                    },
                    "description": "ETag из GET, с кавычками."
                }
            ],
            "get": {
                "summary": "Скачать файл, включая карантин. Ответ — исходные байты; ETag в заголовке.",
                "responses": {
                    "200": {
                        "description": "Байты файла",
                        "headers": {
                            "ETag": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/octet-stream": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "head": {
                "summary": "Метаданные файла в HTTP-заголовках, без тела.",
                "responses": {
                    "200": {
                        "description": "Успех"
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "put": {
                "summary": "Создать файл. Для замены укажите overwrite=1; If-Match защищает от потери параллельных изменений.",
                "responses": {
                    "200": {
                        "description": "Успех",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "entry"
                                    ],
                                    "properties": {
                                        "entry": {
                                            "type": "object",
                                            "required": [
                                                "id",
                                                "site_id",
                                                "path",
                                                "kind",
                                                "size",
                                                "state",
                                                "etag"
                                            ],
                                            "properties": {
                                                "id": {
                                                    "type": "integer"
                                                },
                                                "site_id": {
                                                    "type": "integer"
                                                },
                                                "path": {
                                                    "type": "string"
                                                },
                                                "kind": {
                                                    "type": "string",
                                                    "enum": [
                                                        "file",
                                                        "dir"
                                                    ]
                                                },
                                                "size": {
                                                    "type": "integer"
                                                },
                                                "state": {
                                                    "type": "string",
                                                    "enum": [
                                                        "live",
                                                        "quarantine",
                                                        "trash"
                                                    ]
                                                },
                                                "etag": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ]
                                                }
                                            },
                                            "additionalProperties": true
                                        }
                                    }
                                },
                                "example": {
                                    "entry": {
                                        "id": 42,
                                        "site_id": 1,
                                        "path": "pages/index.html",
                                        "kind": "file",
                                        "size": 34,
                                        "state": "live",
                                        "etag": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                                        "updated_at": 1700000000
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/octet-stream": {
                            "schema": {
                                "type": "string",
                                "format": "binary"
                            },
                            "example": "<!doctype html><h1>Привет</h1>"
                        }
                    }
                }
            },
            "delete": {
                "summary": "Переместить файл или папку в корзину.",
                "responses": {
                    "200": {
                        "description": "Успех"
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/directories": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "summary": "Создать папку. Родительские папки создаются автоматически.",
                "responses": {
                    "200": {
                        "description": "Успех",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "ok": {
                                            "type": "boolean"
                                        }
                                    }
                                },
                                "example": {
                                    "ok": true
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "path": {
                                        "type": "string"
                                    }
                                },
                                "required": [
                                    "path"
                                ]
                            },
                            "example": {
                                "path": "pages"
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/copy": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "summary": "Копировать файл или дерево папок без перезаписи.",
                "responses": {
                    "200": {
                        "description": "Успех"
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "path": {
                                        "type": "string"
                                    },
                                    "to": {
                                        "type": "string"
                                    }
                                },
                                "required": [
                                    "path",
                                    "to"
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/move": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "summary": "Переместить или переименовать без перезаписи.",
                "responses": {
                    "200": {
                        "description": "Успех"
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "path": {
                                        "type": "string"
                                    },
                                    "to": {
                                        "type": "string"
                                    }
                                },
                                "required": [
                                    "path",
                                    "to"
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/upload": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "summary": "Загрузить один файл. ZIP автоматически распаковывается в path; сам архив не сохраняется.",
                "responses": {
                    "200": {
                        "description": "Успех"
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "file"
                                ],
                                "properties": {
                                    "file": {
                                        "type": "string",
                                        "format": "binary"
                                    },
                                    "path": {
                                        "type": "string"
                                    },
                                    "overwrite": {
                                        "type": "boolean",
                                        "default": false
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/archive": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                },
                {
                    "name": "path",
                    "in": "query",
                    "required": false,
                    "schema": {
                        "type": "string"
                    },
                    "description": "Относительный путь от корня сайта; пустая строка — корень."
                }
            ],
            "get": {
                "summary": "Скачать папку или весь сайт (пустой path) как ZIP; включает карантин владельца.",
                "responses": {
                    "200": {
                        "description": "ZIP",
                        "content": {
                            "application/zip": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/trash": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "get": {
                "summary": "Список удалённых объектов. Для восстановления используется trash_batch.",
                "responses": {
                    "200": {
                        "description": "Успех"
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/restore": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "summary": "Восстановить объект корзины. Карантин сохраняется.",
                "responses": {
                    "200": {
                        "description": "Успех"
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "batch": {
                                        "type": "string"
                                    }
                                },
                                "required": [
                                    "batch"
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/purge": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "summary": "Безвозвратно удалить объект корзины.",
                "responses": {
                    "200": {
                        "description": "Успех"
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "batch": {
                                        "type": "string"
                                    }
                                },
                                "required": [
                                    "batch"
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/sites/{site}/optimize": {
            "parameters": [
                {
                    "name": "site",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "summary": "Создать WEBP из растрового изображения. Оригинал сохраняется; первый кадр анимации.",
                "responses": {
                    "200": {
                        "description": "Успех"
                    },
                    "401": {
                        "description": "Токен недействителен",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Токен недействителен",
                                        "status": 401
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Блокировка или недостаточно прав",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Блокировка или недостаточно прав",
                                        "status": 403
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Объект не найден",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Объект не найден",
                                        "status": 404
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Конфликт имени или ETag",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Конфликт имени или ETag",
                                        "status": 409
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "Превышен размер/квота",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Превышен размер/квота",
                                        "status": 413
                                    }
                                }
                            }
                        }
                    },
                    "415": {
                        "description": "Запрещённый формат",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Запрещённый формат",
                                        "status": 415
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Некорректные данные",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "object",
                                            "required": [
                                                "message",
                                                "status"
                                            ],
                                            "properties": {
                                                "message": {
                                                    "type": "string"
                                                },
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "error": {
                                        "message": "Некорректные данные",
                                        "status": 422
                                    }
                                }
                            }
                        }
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "path": {
                                        "type": "string"
                                    },
                                    "width": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 8192,
                                        "default": 1920
                                    },
                                    "height": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 8192,
                                        "default": 1920
                                    },
                                    "quality": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 100,
                                        "default": 80
                                    },
                                    "replace": {
                                        "type": "boolean",
                                        "default": false
                                    }
                                },
                                "required": [
                                    "path"
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/sites/{id}/access": {
            "parameters": [
                {
                    "name": "id",
                    "in": "path",
                    "required": true,
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "get": {
                "summary": "Прочитать правило публичного доступа. Ключ не требуется.",
                "responses": {
                    "200": {
                        "description": "Безопасные сведения о правиле; ключ только при явной генерации.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/AccessResult"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "API-токен отсутствует/истёк/отозван."
                    },
                    "403": {
                        "description": "Запись ограничена блокировкой аккаунта/сайта."
                    },
                    "404": {
                        "description": "Сайт вне прав токена либо объект не существует."
                    },
                    "422": {
                        "description": "Неверный путь, режим или ключ."
                    }
                },
                "parameters": [
                    {
                        "name": "path",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "default": ""
                        },
                        "description": "Точный относительный путь; пусто означает корень."
                    }
                ]
            },
            "put": {
                "summary": "Установить ключ, публичный режим или наследование. Bearer scope обязателен.",
                "responses": {
                    "200": {
                        "description": "Безопасные сведения о правиле; ключ только при явной генерации.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/AccessResult"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "API-токен отсутствует/истёк/отозван."
                    },
                    "403": {
                        "description": "Запись ограничена блокировкой аккаунта/сайта."
                    },
                    "404": {
                        "description": "Сайт вне прав токена либо объект не существует."
                    },
                    "422": {
                        "description": "Неверный путь, режим или ключ."
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/AccessWrite"
                            }
                        }
                    }
                }
            },
            "delete": {
                "summary": "Вернуть наследование; для корня — открытый доступ.",
                "responses": {
                    "200": {
                        "description": "Безопасные сведения о правиле; ключ только при явной генерации.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/AccessResult"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "API-токен отсутствует/истёк/отозван."
                    },
                    "403": {
                        "description": "Запись ограничена блокировкой аккаунта/сайта."
                    },
                    "404": {
                        "description": "Сайт вне прав токена либо объект не существует."
                    },
                    "422": {
                        "description": "Неверный путь, режим или ключ."
                    }
                },
                "parameters": [
                    {
                        "name": "path",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "default": ""
                        },
                        "description": "Точный относительный путь; пусто означает корень."
                    }
                ]
            }
        }
    }
}
