{
  "openapi": "3.1.0",
  "info": {
    "title": "WhatsApp API DietSystem",
    "version": "1.0.0",
    "description": "API para gerenciar sessões WhatsApp, mensagens, filas, webhooks e diagnóstico. Não inclua chaves em payloads ou repositórios."
  },
  "servers": [{"url": "https://zap.dietsystem.com.br", "description": "Produção"}],
  "tags": [
    {"name": "Sistema"}, {"name": "Instâncias"}, {"name": "Mensagens"},
    {"name": "Diagnóstico"}, {"name": "Webhooks"}, {"name": "Permissões locais"},
    {"name": "Compatibilidade UAZAPI"}
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {"type": "http", "scheme": "bearer", "description": "ADMIN_API_KEY"},
      "adminToken": {"type": "apiKey", "in": "header", "name": "admintoken"},
      "instanceToken": {"type": "apiKey", "in": "header", "name": "token"}
    },
    "parameters": {
      "InstanceId": {"name": "id", "in": "path", "required": true, "schema": {"type": "string"}, "description": "ID UUID da instância"},
      "Number": {"name": "number", "in": "path", "required": true, "schema": {"type": "string"}}
    },
    "schemas": {
      "Error": {"type": "object", "required": ["error"], "properties": {"error": {"type": "string"}}, "example": {"error": "instance is not connected/logged in"}},
      "Instance": {"type": "object", "properties": {"id": {"type": "string"}, "token": {"type": "string"}, "name": {"type": "string"}, "status": {"type": "string", "enum": ["disconnected", "connecting", "connected", "hibernated"]}, "owner": {"type": "string"}, "profileName": {"type": "string"}}},
      "TextMessage": {"type": "object", "required": ["number", "text"], "properties": {"number": {"type": "string", "example": "5565999999999"}, "text": {"type": "string", "example": "Olá! Sua consulta está confirmada."}, "async": {"type": "boolean", "default": false}, "idempotencyKey": {"type": "string"}}},
      "MediaMessage": {"type": "object", "required": ["number", "file"], "properties": {"number": {"type": "string"}, "type": {"type": "string", "enum": ["image", "video", "audio", "document"]}, "file": {"type": "string", "description": "URL, base64 ou data URI"}, "text": {"type": "string"}, "fileName": {"type": "string"}, "docName": {"type": "string"}, "async": {"type": "boolean"}, "idempotencyKey": {"type": "string"}}},
      "SendResult": {"type": "object", "properties": {"id": {"type": "string"}, "status": {"type": "string"}, "created": {"type": "boolean"}}},
      "ConsentInput": {"type": "object", "required": ["number"], "properties": {"number": {"type": "string"}, "source": {"type": "string"}}},
      "WebhookInput": {"type": "object", "required": ["url"], "properties": {"url": {"type": "string", "format": "uri"}, "secret": {"type": "string"}, "events": {"oneOf": [{"type": "string"}, {"type": "array", "items": {"type": "string"}}]}, "excludeMessages": {"type": "array", "items": {"type": "string"}}, "addUrlEvents": {"type": "boolean", "default": false}, "addUrlTypesMessages": {"type": "boolean", "default": false}, "enabled": {"type": "boolean"}}},
      "UazapiWebhookConfig": {"type": "object", "required": ["id", "enabled", "url", "events", "excludeMessages", "addUrlEvents", "addUrlTypesMessages"], "properties": {"id": {"type": "string", "format": "uuid"}, "enabled": {"type": "boolean"}, "url": {"type": "string", "format": "uri"}, "events": {"type": "array", "items": {"type": "string"}}, "excludeMessages": {"type": "array", "items": {"type": "string"}}, "addUrlEvents": {"type": "boolean"}, "addUrlTypesMessages": {"type": "boolean"}}}
    },
    "responses": {
      "BadRequest": {"description": "Requisição inválida", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "Unauthorized": {"description": "Chave ausente ou inválida", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "NotFound": {"description": "Recurso não encontrado", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "Conflict": {"description": "Estado da sessão incompatível", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}
    }
  },
  "paths": {
    "/health": {"get": {"tags": ["Sistema"], "summary": "Verificar prontidão e posse do runtime", "security": [], "responses": {"200": {"description": "Runtime ativo", "content": {"application/json": {"example": {"ok": true, "service": "whatsmeow-restserver", "version": "runtime-lease-v1", "runtimeOwner": true}}}}, "503": {"description": "Container em standby"}}}},
    "/live": {"get": {"tags": ["Sistema"], "summary": "Verificar se o processo está vivo", "security": [], "responses": {"200": {"description": "Processo vivo, inclusive em standby"}}}},
    "/metrics": {"get": {"tags": ["Sistema"], "summary": "Obter métricas Prometheus", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Métricas", "content": {"text/plain": {"schema": {"type": "string"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}}}},
    "/webhook/config": {
      "get": {"tags": ["Sistema", "Webhooks"], "summary": "Ler webhook global", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Configuração atual"}, "401": {"$ref": "#/components/responses/Unauthorized"}}},
      "post": {"tags": ["Sistema", "Webhooks"], "summary": "Configurar webhook global", "security": [{"bearerAuth": []}], "requestBody": {"required": true, "content": {"application/json": {"example": {"url": "https://api.exemplo.com/webhooks/whatsapp", "verifyToken": "token-verificacao", "appSecret": "segredo", "enabled": true}}}}, "responses": {"200": {"description": "Configuração salva"}, "400": {"$ref": "#/components/responses/BadRequest"}}}
    },
    "/webhook": {
      "get": {"tags": ["Webhooks", "Compatibilidade UAZAPI"], "summary": "Ler webhook da instância por token ou validar handshake Cloud API", "security": [{"instanceToken": []}, {}], "parameters": [{"name": "token", "in": "header", "schema": {"type": "string"}}, {"name": "hub.mode", "in": "query", "schema": {"type": "string"}}, {"name": "hub.verify_token", "in": "query", "schema": {"type": "string"}}, {"name": "hub.challenge", "in": "query", "schema": {"type": "string"}}], "responses": {"200": {"description": "Array de configuração da instância ou challenge validado", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/UazapiWebhookConfig"}}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "403": {"description": "Verify token Cloud inválido"}}},
      "post": {"tags": ["Compatibilidade UAZAPI"], "summary": "Configurar webhook compatível", "security": [{"instanceToken": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebhookInput"}, "example": {"url": "https://api.exemplo.com/webhooks/uazapi", "enabled": true, "events": ["messages", "connection"], "excludeMessages": ["wasSentByApi", "fromMeYes", "isGroupYes"]}}}}, "responses": {"200": {"description": "Array com o webhook persistido", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/UazapiWebhookConfig"}}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}}}
    },
    "/instances": {
      "get": {"tags": ["Instâncias"], "summary": "Listar instâncias", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Lista", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Instance"}}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}}},
      "post": {"tags": ["Instâncias"], "summary": "Criar instância", "security": [{"bearerAuth": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["name"], "properties": {"name": {"type": "string"}, "adminField01": {"type": "string"}, "webhookUrl": {"type": "string"}, "webhookSecret": {"type": "string"}}}, "example": {"name": "clinica-cuiaba", "adminField01": "unidade-01"}}}}, "responses": {"201": {"description": "Criada", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Instance"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}}}
    },
    "/instances/{id}": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "get": {"tags": ["Instâncias"], "summary": "Obter instância", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Instância", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Instance"}}}}, "404": {"$ref": "#/components/responses/NotFound"}}}, "delete": {"tags": ["Instâncias"], "summary": "Excluir instância, fila e logs", "security": [{"bearerAuth": []}], "responses": {"204": {"description": "Excluída"}, "404": {"$ref": "#/components/responses/NotFound"}}}},
    "/instances/{id}/qr": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "get": {"tags": ["Instâncias"], "summary": "Gerar ou consultar QR Code", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "QR atual", "content": {"application/json": {"example": {"status": "connecting", "qrcode": "data:image/png;base64,...", "code": "2@...", "expiresAt": "2026-07-10T12:00:00Z"}}}}, "409": {"$ref": "#/components/responses/Conflict"}}}},
    "/instances/{id}/qr.png": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "get": {"tags": ["Instâncias"], "summary": "Obter QR Code em PNG", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Imagem PNG", "content": {"image/png": {"schema": {"type": "string", "contentEncoding": "binary"}}}}, "409": {"$ref": "#/components/responses/Conflict"}}}},
    "/instances/{id}/status": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "get": {"tags": ["Instâncias"], "summary": "Consultar estado ao vivo", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Estado", "content": {"application/json": {"example": {"status": "connected", "connected": true, "loggedIn": true, "hibernated": false}}}}}}},
    "/instances/{id}/profile": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "get": {"tags": ["Diagnóstico"], "summary": "Obter perfil da conta", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Perfil"}, "409": {"$ref": "#/components/responses/Conflict"}}}},
    "/instances/{id}/contact": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "get": {"tags": ["Diagnóstico"], "summary": "Consultar contato", "security": [{"bearerAuth": []}], "parameters": [{"name": "number", "in": "query", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Contato"}, "400": {"$ref": "#/components/responses/BadRequest"}}}},
    "/instances/{id}/send/text": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "post": {"tags": ["Mensagens"], "summary": "Enviar texto", "security": [{"bearerAuth": []}], "parameters": [{"name": "Idempotency-Key", "in": "header", "schema": {"type": "string"}}, {"name": "async", "in": "query", "schema": {"type": "boolean"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TextMessage"}}}}, "responses": {"200": {"description": "Enviado", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SendResult"}}}}, "202": {"description": "Enfileirado"}, "409": {"$ref": "#/components/responses/Conflict"}, "429": {"description": "Limite atingido"}}}},
    "/instances/{id}/send/media": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "post": {"tags": ["Mensagens"], "summary": "Enviar mídia", "description": "Aceita JSON com URL/base64/data URI ou multipart/form-data síncrono.", "security": [{"bearerAuth": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MediaMessage"}}, "multipart/form-data": {"schema": {"type": "object", "required": ["number", "file"], "properties": {"number": {"type": "string"}, "type": {"type": "string"}, "text": {"type": "string"}, "fileName": {"type": "string"}, "file": {"type": "string", "format": "binary"}}}}}}, "responses": {"200": {"description": "Enviado"}, "202": {"description": "Enfileirado"}, "409": {"$ref": "#/components/responses/Conflict"}}}},
    "/instances/{id}/queue": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "get": {"tags": ["Mensagens"], "summary": "Consultar fila", "security": [{"bearerAuth": []}], "parameters": [{"name": "status", "in": "query", "schema": {"type": "string"}}, {"name": "limit", "in": "query", "schema": {"type": "integer"}}], "responses": {"200": {"description": "Resumo e jobs"}}}, "delete": {"tags": ["Mensagens"], "summary": "Cancelar fila pendente", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Jobs cancelados"}}}},
    "/instances/{id}/logs": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "get": {"tags": ["Diagnóstico"], "summary": "Listar histórico estruturado", "security": [{"bearerAuth": []}], "parameters": [{"name": "category", "in": "query", "schema": {"type": "string", "enum": ["connection", "send", "queue", "system"]}}, {"name": "level", "in": "query", "schema": {"type": "string", "enum": ["info", "warning", "error"]}}, {"name": "limit", "in": "query", "schema": {"type": "integer"}}, {"name": "before", "in": "query", "schema": {"type": "integer", "format": "int64"}}], "responses": {"200": {"description": "Página de eventos", "content": {"application/json": {"example": {"logs": [{"event": "send_failed", "recipient": "5565999999999", "reason": "instance is not connected/logged in", "details": {"attemptedRecipient": "5565999999999", "errorType": "*main.apiError"}}], "retentionDays": 7}}}}}}},
    "/instances/{id}/webhook": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "post": {"tags": ["Webhooks"], "summary": "Configurar webhook da instância", "security": [{"bearerAuth": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebhookInput"}}}}, "responses": {"200": {"description": "Configurado"}}}},
    "/instances/{id}/consents/{number}": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}, {"$ref": "#/components/parameters/Number"}], "get": {"tags": ["Permissões locais"], "summary": "Consultar permissão local", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Registro local"}, "404": {"$ref": "#/components/responses/NotFound"}}}},
    "/instances/{id}/consents": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "post": {"tags": ["Permissões locais"], "summary": "Registrar permissão local", "security": [{"bearerAuth": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ConsentInput"}}}}, "responses": {"200": {"description": "Permissão registrada"}}}},
    "/instances/{id}/consents/revoke": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "post": {"tags": ["Permissões locais"], "summary": "Revogar permissão local", "security": [{"bearerAuth": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ConsentInput"}}}}, "responses": {"200": {"description": "Opt-out registrado"}}}},
    "/instances/{id}/disconnect": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "post": {"tags": ["Instâncias"], "summary": "Pausar conexão (legado)", "security": [{"bearerAuth": []}], "responses": {"204": {"description": "Pausada"}}}},
    "/instances/{id}/hibernate": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "post": {"tags": ["Instâncias"], "summary": "Hibernar instância", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Hibernada"}}}},
    "/instances/{id}/resume": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "post": {"tags": ["Instâncias"], "summary": "Retomar instância", "security": [{"bearerAuth": []}], "responses": {"202": {"description": "Reconexão solicitada"}}}},
    "/instances/{id}/reset": {"parameters": [{"$ref": "#/components/parameters/InstanceId"}], "post": {"tags": ["Instâncias"], "summary": "Reiniciar runtime", "security": [{"bearerAuth": []}], "responses": {"202": {"description": "Reset solicitado"}, "429": {"description": "Cooldown ativo"}}}},
    "/instance/init": {"post": {"tags": ["Compatibilidade UAZAPI"], "summary": "Criar instância compatível", "security": [{"adminToken": []}], "requestBody": {"required": true, "content": {"application/json": {"example": {"name": "clinica-cuiaba", "adminField01": "unidade-01", "systemName": "DietSystem"}}}}, "responses": {"200": {"description": "Instância e token"}, "401": {"$ref": "#/components/responses/Unauthorized"}}}},
    "/instance/connect": {"post": {"tags": ["Compatibilidade UAZAPI"], "summary": "Gerar QR compatível", "security": [{"instanceToken": []}], "responses": {"200": {"description": "Instância e QR"}}}},
    "/instance/status": {"get": {"tags": ["Compatibilidade UAZAPI"], "summary": "Consultar status compatível", "security": [{"instanceToken": []}], "responses": {"200": {"description": "Estado da instância"}}}},
    "/instance/all": {"get": {"tags": ["Compatibilidade UAZAPI"], "summary": "Listar instâncias compatíveis", "security": [{"adminToken": []}], "responses": {"200": {"description": "Lista de instâncias"}}}},
    "/instance/disconnect": {"post": {"tags": ["Compatibilidade UAZAPI"], "summary": "Desconectar compatível", "security": [{"instanceToken": []}], "responses": {"200": {"description": "Hibernada"}}}},
    "/instance/hibernate": {"post": {"tags": ["Compatibilidade UAZAPI"], "summary": "Hibernar compatível", "security": [{"instanceToken": []}], "responses": {"200": {"description": "Hibernada"}}}},
    "/instance/resume": {"post": {"tags": ["Compatibilidade UAZAPI"], "summary": "Retomar compatível", "security": [{"instanceToken": []}], "responses": {"202": {"description": "Reconexão solicitada"}}}},
    "/instance/reset": {"post": {"tags": ["Compatibilidade UAZAPI"], "summary": "Reset compatível", "security": [{"instanceToken": []}], "responses": {"202": {"description": "Reset solicitado"}}}},
    "/instance": {"delete": {"tags": ["Compatibilidade UAZAPI"], "summary": "Excluir instância compatível", "security": [{"instanceToken": []}], "responses": {"200": {"description": "Excluída"}}}},
    "/send/text": {"post": {"tags": ["Compatibilidade UAZAPI"], "summary": "Enviar texto compatível", "security": [{"instanceToken": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TextMessage"}}}}, "responses": {"200": {"description": "Enviado"}, "202": {"description": "Enfileirado"}}}},
    "/send/media": {"post": {"tags": ["Compatibilidade UAZAPI"], "summary": "Enviar mídia compatível", "security": [{"instanceToken": []}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MediaMessage"}}}}, "responses": {"200": {"description": "Enviada"}, "202": {"description": "Enfileirada"}}}},
    "/message/async": {"get": {"tags": ["Compatibilidade UAZAPI"], "summary": "Consultar fila compatível", "security": [{"instanceToken": []}], "responses": {"200": {"description": "Estado da fila"}}}, "delete": {"tags": ["Compatibilidade UAZAPI"], "summary": "Cancelar fila compatível", "security": [{"instanceToken": []}], "responses": {"200": {"description": "Jobs cancelados"}}}}
  }
}
