{
  "components": {
    "schemas": {
      "APIKey": {
        "properties": {
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "revoked_at": {
            "format": "date-time",
            "type": "string"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "APIKeyListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/APIKey"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "APIKeySecretResponse": {
        "properties": {
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "secret": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "File": {
        "properties": {
          "checksum": {
            "type": "string"
          },
          "compression_percent": {
            "type": "integer"
          },
          "extension": {
            "type": "string"
          },
          "height": {
            "type": "integer"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "immutable": {
            "description": "Quando true, arquivo não pode ser apagado nem modificado via API.",
            "type": "boolean"
          },
          "kind": {
            "type": "string"
          },
          "media_type": {
            "enum": [
              "image",
              "document",
              "video",
              "audio",
              "other"
            ],
            "type": "string"
          },
          "metadata": {
            "additionalProperties": true,
            "type": "object"
          },
          "mime": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "original_size": {
            "type": "integer"
          },
          "project_id": {
            "format": "uuid",
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "url": {
            "description": "URL de download assinada, com validade limitada (TTL, APP_CDN_DOWNLOAD_TTL). Gerada via CDN quando APP_CDN_DOMAIN está configurado, senão via presigned GET do storage (S3/MinIO). Presente para original, optimized, thumbnail, webp e avif. Como expira, não persista o valor.",
            "type": "string"
          },
          "variant_of": {
            "format": "uuid",
            "type": "string"
          },
          "width": {
            "type": "integer"
          }
        },
        "type": "object"
      },
      "FileListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/File"
            },
            "type": "array"
          },
          "next_cursor": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "HealthResponse": {
        "properties": {
          "status": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "JobAccepted": {
        "properties": {
          "job_id": {
            "format": "uuid",
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "JobDetail": {
        "properties": {
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "error": {
            "type": "string"
          },
          "finished_at": {
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "input": {
            "additionalProperties": true,
            "type": "object"
          },
          "kind": {
            "type": "string"
          },
          "result": {
            "additionalProperties": true,
            "description": "Resultado do job concluído. Saídas únicas (compress/convert/resize/watermark) incluem output_file_id, output_url, size, original_size e compression_percent. Derivações (derive) incluem variants (kind→id), variants_urls e variants_stats (kind→{size, original_size, compression_percent}). compression_percent é o percentual de economia de bytes frente ao original.",
            "type": "object"
          },
          "status": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "LoginResponse": {
        "properties": {
          "access_token": {
            "type": "string"
          },
          "expires_at": {
            "format": "date-time",
            "type": "string"
          },
          "user": {
            "$ref": "#/components/schemas/UserResponse"
          }
        },
        "type": "object"
      },
      "PresignedUploadResponse": {
        "properties": {
          "file": {
            "$ref": "#/components/schemas/File"
          },
          "upload_url": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "ProblemDetails": {
        "properties": {
          "code": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "ReadinessResponse": {
        "properties": {
          "checks": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object"
          },
          "status": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "TenantCompressSettingsResponse": {
        "properties": {
          "format": {
            "type": "string"
          },
          "keep_original": {
            "type": "boolean"
          },
          "max_bytes": {
            "type": "integer"
          },
          "max_dimension": {
            "type": "integer"
          },
          "next_gen": {
            "enum": [
              "off",
              "webp",
              "avif",
              "both"
            ],
            "type": "string"
          },
          "png_to_jpeg": {
            "type": "boolean"
          },
          "quality": {
            "type": "integer"
          },
          "strip_exif": {
            "type": "boolean"
          },
          "thumbnail_format": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "TenantCreatedResponse": {
        "properties": {
          "domain": {
            "nullable": true,
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "plan_id": {
            "format": "uuid",
            "type": "string"
          },
          "slug": {
            "type": "string"
          }
        },
        "type": "object"
      },
      "TenantFileSettingsResponse": {
        "properties": {
          "allowed_extensions": {
            "description": "Extensões permitidas para upload neste tenant",
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "TenantListItem": {
        "properties": {
          "domain": {
            "nullable": true,
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "plan_id": {
            "format": "uuid",
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "status": {
            "enum": [
              "active",
              "suspended",
              "deleted"
            ],
            "type": "string"
          }
        },
        "type": "object"
      },
      "TenantListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/TenantListItem"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "TenantPDFSettingsResponse": {
        "properties": {
          "default_profile": {
            "type": "string"
          },
          "keep_original": {
            "type": "boolean"
          },
          "sanitize": {
            "type": "boolean"
          },
          "strip_js": {
            "type": "boolean"
          },
          "target_compression_percent": {
            "maximum": 95,
            "minimum": 1,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "TenantResponse": {
        "properties": {
          "bucket": {
            "type": "string"
          },
          "domain": {
            "nullable": true,
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "plan_id": {
            "format": "uuid",
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "status": {
            "enum": [
              "active",
              "suspended",
              "deleted"
            ],
            "type": "string"
          },
          "webhook_url": {
            "format": "uri",
            "nullable": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "TenantUsageResponse": {
        "properties": {
          "jobs": {
            "properties": {
              "done": {
                "type": "integer"
              },
              "failed": {
                "type": "integer"
              },
              "queued": {
                "type": "integer"
              },
              "running": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              }
            },
            "type": "object"
          },
          "period_month": {
            "type": "string"
          },
          "plan": {
            "properties": {
              "id": {
                "format": "uuid",
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "requests": {
            "properties": {
              "limit": {
                "type": "integer"
              },
              "used": {
                "type": "integer"
              }
            },
            "type": "object"
          },
          "storage": {
            "properties": {
              "bytes_limit": {
                "type": "integer"
              },
              "bytes_used": {
                "type": "integer"
              },
              "files_total": {
                "type": "integer"
              }
            },
            "type": "object"
          },
          "tenant_id": {
            "format": "uuid",
            "type": "string"
          }
        },
        "type": "object"
      },
      "UserListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/UserResponse"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "UserResponse": {
        "properties": {
          "created_at": {
            "format": "date-time",
            "type": "string"
          },
          "email": {
            "format": "email",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "enum": [
              "root",
              "admin"
            ],
            "type": "string"
          },
          "status": {
            "enum": [
              "active",
              "disabled"
            ],
            "type": "string"
          },
          "updated_at": {
            "format": "date-time",
            "type": "string"
          }
        },
        "type": "object"
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "bearerFormat": "APIKey",
        "scheme": "bearer",
        "type": "http"
      },
      "UserJWT": {
        "bearerFormat": "JWT",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "description": "API HTTP do imgflow para autenticação por API key, JWT administrativo, arquivos, imagens, PDFs, jobs e gestão de tenants.",
    "title": "imgflow API",
    "version": "v1"
  },
  "openapi": "3.1.0",
  "paths": {
    "/healthz": {
      "get": {
        "operationId": "health.liveness",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            },
            "description": "Processo vivo"
          }
        },
        "summary": "Liveness da aplicação",
        "tags": [
          "health"
        ]
      }
    },
    "/readyz": {
      "get": {
        "operationId": "health.readiness",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            },
            "description": "Dependências prontas"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            },
            "description": "Dependência indisponível"
          }
        },
        "summary": "Readiness das dependências",
        "tags": [
          "health"
        ]
      }
    },
    "/v1/files": {
      "get": {
        "operationId": "files.list",
        "parameters": [
          {
            "description": "Slug do projeto.",
            "in": "query",
            "name": "project",
            "schema": {
              "default": "default",
              "type": "string"
            }
          },
          {
            "description": "Máximo de itens por página.",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 100,
              "type": "integer"
            }
          },
          {
            "description": "Cursor de paginação keyset (UUID v7).",
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Filtro opcional: true = só imutáveis (contratos); false = só operacionais; omitido = todos.",
            "in": "query",
            "name": "immutable",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileListResponse"
                }
              }
            },
            "description": "Lista paginada de arquivos"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Parâmetro immutable inválido"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Listar arquivos por projeto",
        "tags": [
          "files"
        ]
      },
      "post": {
        "operationId": "files.upload",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "file": {
                    "format": "binary",
                    "type": "string"
                  },
                  "immutable": {
                    "description": "Quando true, arquivo não pode ser apagado nem modificado via API (contratos assinados).",
                    "type": "boolean"
                  },
                  "project": {
                    "type": "string"
                  }
                },
                "required": [
                  "file"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                }
              }
            },
            "description": "Arquivo criado"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Extensão ou tipo de mídia bloqueado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Multipart inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Upload síncrono de arquivo",
        "tags": [
          "files"
        ]
      }
    },
    "/v1/files/{id}": {
      "delete": {
        "operationId": "files.delete",
        "responses": {
          "204": {
            "description": "Arquivo removido"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo não encontrado"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Remover arquivo",
        "tags": [
          "files"
        ]
      },
      "get": {
        "operationId": "files.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                }
              }
            },
            "description": "Arquivo encontrado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo não encontrado"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Consultar metadados do arquivo",
        "tags": [
          "files"
        ]
      }
    },
    "/v1/files/{id}/download": {
      "get": {
        "operationId": "files.download",
        "responses": {
          "302": {
            "description": "Redirect para URL de download assinada (CDN ou presigned do storage)"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo não encontrado"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Gerar redirect para download",
        "tags": [
          "files"
        ]
      }
    },
    "/v1/img/compress": {
      "post": {
        "operationId": "img.compress",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "file_id": {
                    "format": "uuid",
                    "type": "string"
                  },
                  "format": {
                    "type": "string"
                  },
                  "max_bytes": {
                    "type": "integer"
                  },
                  "max_dimension": {
                    "type": "integer"
                  },
                  "quality": {
                    "type": "integer"
                  },
                  "strip_exif": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "file_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar compressão de imagem",
        "tags": [
          "img"
        ]
      }
    },
    "/v1/img/convert": {
      "post": {
        "operationId": "img.convert",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "file_id": {
                    "format": "uuid",
                    "type": "string"
                  },
                  "format": {
                    "type": "string"
                  }
                },
                "required": [
                  "file_id",
                  "format"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar conversão de imagem",
        "tags": [
          "img"
        ]
      }
    },
    "/v1/img/resize": {
      "post": {
        "operationId": "img.resize",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "file_id": {
                    "format": "uuid",
                    "type": "string"
                  },
                  "height": {
                    "type": "integer"
                  },
                  "mode": {
                    "type": "string"
                  },
                  "upscale": {
                    "type": "boolean"
                  },
                  "width": {
                    "type": "integer"
                  }
                },
                "required": [
                  "file_id",
                  "width",
                  "height"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar resize de imagem",
        "tags": [
          "img"
        ]
      }
    },
    "/v1/img/upload": {
      "post": {
        "operationId": "img.upload",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "file": {
                    "format": "binary",
                    "type": "string"
                  },
                  "project": {
                    "type": "string"
                  }
                },
                "required": [
                  "file"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                }
              }
            },
            "description": "Imagem criada"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Extensão ou tipo de mídia bloqueado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Upload de imagem",
        "tags": [
          "img"
        ]
      }
    },
    "/v1/img/watermark": {
      "post": {
        "operationId": "img.watermark",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "file_id": {
                    "format": "uuid",
                    "type": "string"
                  },
                  "opacity": {
                    "type": "number"
                  },
                  "position": {
                    "type": "string"
                  },
                  "watermark_file_id": {
                    "format": "uuid",
                    "type": "string"
                  }
                },
                "required": [
                  "file_id",
                  "watermark_file_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar watermark de imagem",
        "tags": [
          "img"
        ]
      }
    },
    "/v1/jobs/{id}": {
      "get": {
        "operationId": "jobs.get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobDetail"
                }
              }
            },
            "description": "Detalhe do job"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Job não encontrado"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Consultar job assíncrono",
        "tags": [
          "jobs"
        ]
      }
    },
    "/v1/openapi.json": {
      "get": {
        "operationId": "openapi.document",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "description": "Spec OpenAPI em JSON"
          }
        },
        "summary": "Documento OpenAPI",
        "tags": [
          "openapi"
        ]
      }
    },
    "/v1/pdf/compress": {
      "post": {
        "operationId": "pdf.compress",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "file_id": {
                    "format": "uuid",
                    "type": "string"
                  },
                  "profile": {
                    "enum": [
                      "screen",
                      "ebook",
                      "print"
                    ],
                    "type": "string"
                  },
                  "sanitize": {
                    "type": "boolean"
                  },
                  "strip_js": {
                    "type": "boolean"
                  },
                  "target_compression_percent": {
                    "maximum": 95,
                    "minimum": 1,
                    "type": "integer"
                  }
                },
                "required": [
                  "file_id"
                ],
                "type": "object"
              }
            },
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "file": {
                    "format": "binary",
                    "type": "string"
                  },
                  "profile": {
                    "enum": [
                      "screen",
                      "ebook",
                      "print"
                    ],
                    "type": "string"
                  },
                  "project": {
                    "type": "string"
                  },
                  "sanitize": {
                    "type": "boolean"
                  },
                  "strip_js": {
                    "type": "boolean"
                  },
                  "target_compression_percent": {
                    "maximum": 95,
                    "minimum": 1,
                    "type": "integer"
                  }
                },
                "required": [
                  "file"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar compressão de PDF (JSON com file_id ou multipart com file)",
        "tags": [
          "pdf"
        ]
      }
    },
    "/v1/pdf/compress/upload": {
      "post": {
        "operationId": "pdf.compressUpload",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "properties": {
                  "file": {
                    "format": "binary",
                    "type": "string"
                  },
                  "profile": {
                    "enum": [
                      "screen",
                      "ebook",
                      "print"
                    ],
                    "type": "string"
                  },
                  "project": {
                    "type": "string"
                  },
                  "sanitize": {
                    "type": "boolean"
                  },
                  "strip_js": {
                    "type": "boolean"
                  },
                  "target_compression_percent": {
                    "maximum": 95,
                    "minimum": 1,
                    "type": "integer"
                  }
                },
                "required": [
                  "file"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                }
              }
            },
            "description": "PDF comprimido gravado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Upload multipart de PDF com compressão síncrona em private/",
        "tags": [
          "pdf"
        ]
      }
    },
    "/v1/pdf/merge": {
      "post": {
        "operationId": "pdf.merge",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "file_ids": {
                    "items": {
                      "format": "uuid",
                      "type": "string"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "file_ids"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar merge de PDFs",
        "tags": [
          "pdf"
        ]
      }
    },
    "/v1/pdf/protect": {
      "post": {
        "operationId": "pdf.protect",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "file_id": {
                    "format": "uuid",
                    "type": "string"
                  },
                  "owner_password": {
                    "type": "string"
                  },
                  "user_password": {
                    "type": "string"
                  }
                },
                "required": [
                  "file_id",
                  "user_password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar proteção de PDF",
        "tags": [
          "pdf"
        ]
      }
    },
    "/v1/pdf/rotate": {
      "post": {
        "operationId": "pdf.rotate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "degrees": {
                    "type": "integer"
                  },
                  "file_id": {
                    "format": "uuid",
                    "type": "string"
                  }
                },
                "required": [
                  "file_id",
                  "degrees"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar rotação de PDF",
        "tags": [
          "pdf"
        ]
      }
    },
    "/v1/pdf/split": {
      "post": {
        "operationId": "pdf.split",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "file_id": {
                    "format": "uuid",
                    "type": "string"
                  },
                  "ranges": {
                    "items": {
                      "properties": {
                        "from": {
                          "type": "integer"
                        },
                        "to": {
                          "type": "integer"
                        }
                      },
                      "type": "object"
                    },
                    "type": "array"
                  }
                },
                "required": [
                  "file_id",
                  "ranges"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar split de PDF",
        "tags": [
          "pdf"
        ]
      }
    },
    "/v1/pdf/thumbnail": {
      "post": {
        "operationId": "pdf.thumbnail",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "dpi": {
                    "type": "integer"
                  },
                  "file_id": {
                    "format": "uuid",
                    "type": "string"
                  },
                  "height": {
                    "type": "integer"
                  },
                  "page": {
                    "type": "integer"
                  },
                  "width": {
                    "type": "integer"
                  }
                },
                "required": [
                  "file_id"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                }
              }
            },
            "description": "Job enfileirado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Escopo insuficiente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Arquivo imutável"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Enfileirar thumbnail de PDF",
        "tags": [
          "pdf"
        ]
      }
    },
    "/v1/tenancy/tenants": {
      "get": {
        "operationId": "tenancy.listTenants",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 100,
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "status",
            "schema": {
              "enum": [
                "active",
                "suspended",
                "deleted"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantListResponse"
                }
              }
            },
            "description": "Lista de tenants"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Parâmetros inválidos"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Listar tenants",
        "tags": [
          "tenancy"
        ]
      },
      "post": {
        "operationId": "tenancy.createTenant",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "domain": {
                    "description": "Domínio white label opcional (ex.: fotos.cliente.com)",
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "plan_name": {
                    "default": "free",
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "slug"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCreatedResponse"
                }
              }
            },
            "description": "Tenant criado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Domínio já em uso"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Criar tenant",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}": {
      "delete": {
        "operationId": "tenancy.deleteTenant",
        "responses": {
          "204": {
            "description": "Tenant marcado como excluído"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant não encontrado"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Excluir tenant (soft delete)",
        "tags": [
          "tenancy"
        ]
      },
      "get": {
        "operationId": "tenancy.getTenant",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponse"
                }
              }
            },
            "description": "Tenant"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant não encontrado"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Consultar tenant",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/activate": {
      "post": {
        "operationId": "tenancy.activateTenant",
        "responses": {
          "204": {
            "description": "Tenant ativado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant não encontrado"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Ativar tenant (active)",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/api-keys": {
      "get": {
        "operationId": "tenant.listApiKeys",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIKeyListResponse"
                }
              }
            },
            "description": "Lista de API keys"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant não encontrado"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Parâmetros inválidos"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Listar API keys de um tenant (root)",
        "tags": [
          "tenant-api-keys"
        ]
      },
      "post": {
        "operationId": "tenant.createApiKey",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "scopes": {
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIKeySecretResponse"
                }
              }
            },
            "description": "API key criada"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant não encontrado"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Criar API key administrativa para tenant",
        "tags": [
          "tenant-api-keys"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/api-keys/{id}": {
      "delete": {
        "operationId": "tenant.revokeApiKey",
        "parameters": [
          {
            "in": "path",
            "name": "tenant_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Quando true, remove a key do banco (hard delete). Sem este parâmetro, apenas revoga (soft delete).",
            "in": "query",
            "name": "hard",
            "required": false,
            "schema": {
              "default": false,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "API key revogada ou excluída"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant ou API key não encontrados"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Parâmetros inválidos"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Revogar ou excluir API key de um tenant (root)",
        "tags": [
          "tenant-api-keys"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/domain": {
      "put": {
        "operationId": "tenancy.setDomain",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "domain": {
                    "description": "Hostname white label; null ou string vazia remove o domínio",
                    "nullable": true,
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Domínio atualizado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant não encontrado"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Domínio já em uso"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Definir domínio white label do tenant",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/file-settings": {
      "get": {
        "operationId": "tenancy.getFileSettings",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantFileSettingsResponse"
                }
              }
            },
            "description": "Allowlist de upload"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant ou settings não encontrados"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Consultar allowlist de upload do tenant",
        "tags": [
          "tenancy"
        ]
      },
      "put": {
        "operationId": "tenancy.updateFileSettings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "allowed_extensions": {
                    "description": "Extensões permitidas, sem ponto inicial (ex.: pdf, png, docx). Lista vazia rejeita todos os uploads.",
                    "items": {
                      "type": "string"
                    },
                    "type": "array"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantFileSettingsResponse"
                }
              }
            },
            "description": "Allowlist atualizada"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant ou settings não encontrados"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Atualizar allowlist de upload do tenant",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/img-settings/compress": {
      "get": {
        "operationId": "tenancy.getCompressSettings",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCompressSettingsResponse"
                }
              }
            },
            "description": "Defaults de compressão"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant ou settings não encontrados"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Consultar defaults de compressão do tenant",
        "tags": [
          "tenancy"
        ]
      },
      "put": {
        "operationId": "tenancy.updateCompressSettings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "format": {
                    "enum": [
                      "jpeg",
                      "png",
                      "webp",
                      "avif"
                    ],
                    "type": "string"
                  },
                  "keep_original": {
                    "type": "boolean"
                  },
                  "max_bytes": {
                    "minimum": 1,
                    "type": "integer"
                  },
                  "max_dimension": {
                    "maximum": 10000,
                    "minimum": 1,
                    "type": "integer"
                  },
                  "next_gen": {
                    "description": "Gera sidecars next-gen após o optimized. avif/both exigem processor=vips.",
                    "enum": [
                      "off",
                      "webp",
                      "avif",
                      "both"
                    ],
                    "type": "string"
                  },
                  "png_to_jpeg": {
                    "description": "Converte PNG opaco para JPEG antes da compressão. PNGs com transparência nunca são convertidos.",
                    "type": "boolean"
                  },
                  "quality": {
                    "maximum": 100,
                    "minimum": 1,
                    "type": "integer"
                  },
                  "strip_exif": {
                    "type": "boolean"
                  },
                  "thumbnail_format": {
                    "enum": [
                      "jpeg",
                      "webp"
                    ],
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCompressSettingsResponse"
                }
              }
            },
            "description": "Defaults atualizados"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant ou settings não encontrados"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Atualizar defaults de compressão do tenant",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/pdf-settings/compress": {
      "get": {
        "operationId": "tenancy.getPDFCompressSettings",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPDFSettingsResponse"
                }
              }
            },
            "description": "Defaults de compressão PDF"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant ou settings não encontrados"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Consultar defaults de compressão PDF do tenant",
        "tags": [
          "tenancy"
        ]
      },
      "put": {
        "operationId": "tenancy.updatePDFCompressSettings",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "default_profile": {
                    "enum": [
                      "screen",
                      "ebook",
                      "print"
                    ],
                    "type": "string"
                  },
                  "keep_original": {
                    "description": "Quando false, remove o PDF original após compressão bem-sucedida",
                    "type": "boolean"
                  },
                  "sanitize": {
                    "type": "boolean"
                  },
                  "strip_js": {
                    "type": "boolean"
                  },
                  "target_compression_percent": {
                    "maximum": 95,
                    "minimum": 1,
                    "type": "integer"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPDFSettingsResponse"
                }
              }
            },
            "description": "Defaults atualizados"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant ou settings não encontrados"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Atualizar defaults de compressão PDF do tenant",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/suspend": {
      "post": {
        "operationId": "tenancy.suspendTenant",
        "responses": {
          "204": {
            "description": "Tenant inativado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant não encontrado"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant excluído"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Inativar tenant (suspended)",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/usage": {
      "get": {
        "operationId": "tenancy.getUsage",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantUsageResponse"
                }
              }
            },
            "description": "Resumo de uso do tenant"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant não encontrado"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Consultar resumo de uso do tenant",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/tenancy/tenants/{tenant_id}/webhook": {
      "put": {
        "operationId": "tenancy.setWebhook",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "secret": {
                    "type": "string"
                  },
                  "url": {
                    "format": "uri",
                    "type": "string"
                  }
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "204": {
            "description": "Webhook configurado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Token administrativo ausente"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Tenant não encontrado"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Payload inválido"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Configurar webhook do tenant",
        "tags": [
          "tenancy"
        ]
      }
    },
    "/v1/user": {
      "get": {
        "operationId": "user.listUsers",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserListResponse"
                }
              }
            },
            "description": "Lista de usuários"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Somente root"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Listar usuários (root)",
        "tags": [
          "user"
        ]
      },
      "post": {
        "operationId": "user.createUser",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "email": {
                    "format": "email",
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  },
                  "role": {
                    "enum": [
                      "admin"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "email",
                  "password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            },
            "description": "Usuário criado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Somente root"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Criar usuário admin (root)",
        "tags": [
          "user"
        ]
      }
    },
    "/v1/user/change-email": {
      "post": {
        "operationId": "user.changeEmail",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "new_email": {
                    "format": "email",
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  }
                },
                "required": [
                  "password",
                  "new_email"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "status": {
                      "example": "updated",
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "E-mail alterado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Credenciais inválidas"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Alterar e-mail",
        "tags": [
          "user"
        ]
      }
    },
    "/v1/user/change-password": {
      "post": {
        "operationId": "user.changePassword",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "current_password": {
                    "type": "string"
                  },
                  "new_password": {
                    "type": "string"
                  }
                },
                "required": [
                  "current_password",
                  "new_password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "status": {
                      "example": "updated",
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Senha alterada"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Credenciais inválidas"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Alterar senha",
        "tags": [
          "user"
        ]
      }
    },
    "/v1/user/login": {
      "post": {
        "operationId": "user.login",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "properties": {
                  "email": {
                    "format": "email",
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  }
                },
                "required": [
                  "email",
                  "password"
                ],
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoginResponse"
                }
              }
            },
            "description": "Login bem-sucedido"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Credenciais inválidas"
          }
        },
        "summary": "Login administrativo",
        "tags": [
          "user"
        ]
      }
    },
    "/v1/user/logout": {
      "post": {
        "operationId": "user.logout",
        "responses": {
          "204": {
            "description": "Token revogado"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Logout (revoga JWT)",
        "tags": [
          "user"
        ]
      }
    },
    "/v1/user/me": {
      "get": {
        "operationId": "user.getMe",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            },
            "description": "Usuário"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Não autenticado"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Dados do usuário autenticado",
        "tags": [
          "user"
        ]
      }
    },
    "/v1/user/{id}": {
      "delete": {
        "operationId": "user.deleteUser",
        "responses": {
          "204": {
            "description": "Usuário excluído"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Somente root"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Usuário não encontrado"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Excluir usuário (root)",
        "tags": [
          "user"
        ]
      }
    },
    "/v1/user/{id}/disable": {
      "post": {
        "operationId": "user.disableUser",
        "responses": {
          "204": {
            "description": "Usuário desativado"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "description": "Somente root"
          }
        },
        "security": [
          {
            "UserJWT": []
          }
        ],
        "summary": "Desativar usuário (root)",
        "tags": [
          "user"
        ]
      }
    }
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "tags": [
    {
      "description": "Health checks públicos",
      "name": "health"
    },
    {
      "description": "Documento OpenAPI publicado pela API",
      "name": "openapi"
    },
    {
      "description": "Gestão de tenants (JWT root)",
      "name": "tenancy"
    },
    {
      "description": "Gestão de API keys do tenant (JWT root)",
      "name": "tenant-api-keys"
    },
    {
      "description": "Login e gestão de usuários administrativos",
      "name": "user"
    },
    {
      "description": "Upload e consulta de arquivos",
      "name": "files"
    },
    {
      "description": "Processamento assíncrono de imagens",
      "name": "img"
    },
    {
      "description": "Processamento assíncrono de PDFs",
      "name": "pdf"
    },
    {
      "description": "Consulta de jobs assíncronos",
      "name": "jobs"
    }
  ]
}