{
  "openapi": "3.1.0",
  "info": {
    "title": "APIFacil WhatsApp API",
    "version": "1.0.0",
    "description": "Plataforma SaaS de API WhatsApp multi-instancia. Todas as rotas publicas usam middleware `auth.api` (Sanctum) com rate limiting. Rotas internas usam `auth.inner` e nao sao documentadas publicamente.",
    "contact": {
      "name": "APIFacil Suporte",
      "url": "https://apifacil.dev",
      "email": "suporte@apifacil.dev"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://apifacil.dev/api/v1",
      "description": "Producao"
    },
    {
      "url": "http://localhost:8001/api/v1",
      "description": "Desenvolvimento local"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerToken": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Token de API (sem prefixo Bearer). Enviar no header: Authorization: {seu_token}"
      }
    },
    "responses": {
      "ValidationError": {
        "description": "Erro de validacao de dados",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": {
              "error": true,
              "message": "Erro de validacao",
              "data": {
                "errors": {
                  "telefone": ["O telefone e obrigatorio"],
                  "mensagem": ["A mensagem e obrigatoria"]
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Token invalido ou ausente",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": {
              "error": true,
              "message": "Nao autorizado",
              "data": null
            }
          }
        }
      },
      "RateLimit": {
        "description": "Limite de requisicoes excedido",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": {
              "error": true,
              "message": "Muitas requisicoes. Tente novamente em alguns segundos.",
              "data": null
            }
          }
        }
      },
      "ServerError": {
        "description": "Erro interno do servidor",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": {
              "error": true,
              "message": "Contate o suporte para mais informacoes",
              "data": null
            }
          }
        }
      },
      "NotFound": {
        "description": "Recurso nao encontrado",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": {
              "error": true,
              "message": "Instancia nao encontrada ou nao pertence ao usuario.",
              "data": null
            }
          }
        }
      },
      "Forbidden": {
        "description": "Recurso nao disponivel no plano ou sem permissao",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": {
              "error": true,
              "message": "Recurso nao disponivel no plano atual. O envio de imagens nao esta disponivel no plano gratuito. Faca upgrade para um plano pago.",
              "data": null
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": { "type": "boolean", "example": true },
          "message": { "type": "string" },
          "data": { "type": "object", "nullable": true }
        },
        "required": ["error", "message"]
      },
      "SuccessResponse": {
        "type": "object",
        "properties": {
          "error": { "type": "boolean", "example": false },
          "message": { "type": "string" },
          "data": { "type": "object", "nullable": true }
        },
        "required": ["error"]
      },
      "NotificacaoResponse": {
        "type": "object",
        "properties": {
          "error": { "type": "boolean", "example": false },
          "message": { "type": "string", "example": "Mensagem adicionada na fila para processamento" },
          "data": {
            "type": "object",
            "properties": {
              "notificacao_id": { "type": "integer", "example": 12345 },
              "message": { "type": "string", "example": "Mensagem adicionada na fila para processamento" }
            }
          }
        }
      },
      "InstanciaCriar": {
        "type": "object",
        "properties": {
          "nome": { "type": "string", "example": "Instancia Principal", "description": "Nome identificador da instancia" },
          "webhook_url": { "type": "string", "format": "uri", "nullable": true, "description": "URL do webhook para mensagens (apenas planos pagos)" },
          "webhook_status": { "type": "string", "format": "uri", "nullable": true, "description": "URL do webhook para mudancas de status (apenas planos pagos)" },
          "webhook_grupo": { "type": "string", "format": "uri", "nullable": true, "description": "URL do webhook para grupos (apenas planos pagos)" }
        },
        "required": ["nome"]
      },
      "InstanciaDetalhes": {
        "type": "object",
        "properties": {
          "instancia": {
            "type": "object",
            "properties": {
              "id": { "type": "integer", "example": 14 },
              "codigo": { "type": "string", "nullable": true },
              "nome": { "type": "string", "example": "Instancia Principal" },
              "public_token": { "type": "string", "example": "a1b2c3d4e5f6..." },
              "status": { "type": "string", "enum": ["connected", "disconnected", "inactive", "connecting", "pairing"], "example": "connected" },
              "tipo_cobranca": { "type": "string", "enum": ["AVULSO", "MENSAL"], "example": "MENSAL" },
              "metadata": { "type": "object", "nullable": true },
              "status_updated_at": { "type": "string", "format": "date-time", "nullable": true },
              "created_at": { "type": "string", "format": "date-time" },
              "updated_at": { "type": "string", "format": "date-time" }
            }
          },
          "configuracao": {
            "type": "object",
            "nullable": true,
            "properties": {
              "webhook_url": { "type": "string", "nullable": true },
              "webhook_status": { "type": "string", "nullable": true },
              "webhook_grupo": { "type": "string", "nullable": true },
              "webhook_ativo": { "type": "boolean" },
              "config_json": { "type": "object" }
            }
          },
          "aquecimento": {
            "type": "object",
            "nullable": true,
            "properties": {
              "ativo": { "type": "boolean" },
              "numeros": { "type": "integer" },
              "mensagens": { "type": "string", "nullable": true }
            }
          }
        }
      }
    }
  },
  "security": [{ "BearerToken": [] }],
  "tags": [
    { "name": "Instancias", "description": "Criar, listar, gerenciar e deletar instancias WhatsApp" },
    { "name": "Conexao", "description": "Conectar instancias via QR Code, Pairing Code ou Importar Sessao" },
    { "name": "Mensagens", "description": "Enviar mensagens de texto, midia e interativas" },
    { "name": "Grupos", "description": "Listar e enviar mensagens/arquivos para grupos WhatsApp" },
    { "name": "Notificacoes", "description": "Consultar e gerenciar notificacoes de envio" },
    { "name": "Configuracoes", "description": "Configurar webhooks e comportamento da instancia" },
    { "name": "Publico", "description": "Endpoints publicos sem autenticacao" }
  ],
  "paths": {
    "/whatsapp/instancia/criar": {
      "post": {
        "tags": ["Instancias"],
        "summary": "Criar nova instancia WhatsApp",
        "description": "Cria uma nova instancia WhatsApp. Verifica limites do plano e atribui um servidor automaticamente. Plano free nao pode configurar webhooks.",
        "operationId": "criarInstancia",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/InstanciaCriar" },
              "example": {
                "nome": "Instancia Principal",
                "webhook_url": "https://meusite.com/webhook",
                "webhook_status": "https://meusite.com/webhook/status"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Instancia criada com sucesso",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "Instancia criada com sucesso",
                  "data": {
                    "instancia_id": 14,
                    "nome": "Instancia Principal",
                    "status": "inactive",
                    "token": "a1b2c3d4e5f6...",
                    "tipo_cobranca": "MENSAL",
                    "detalhes_limite": null
                  }
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/instancia/listar": {
      "get": {
        "tags": ["Instancias"],
        "summary": "Listar todas as instancias do usuario",
        "operationId": "listarInstancias",
        "responses": {
          "200": {
            "description": "Lista de instancias",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "",
                  "data": [
                    {
                      "id": 14,
                      "nome": "Instancia Principal",
                      "public_token": "a1b2c3d4e5f6...",
                      "status": "connected",
                      "created_at": "2025-07-01T10:00:00.000000Z",
                      "codigo": null,
                      "metadata": {
                        "nome": "Joao Silva",
                        "numero": "5511999999999",
                        "plataforma": "web"
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/whatsapp/instancia/{id}/detalhes": {
      "get": {
        "tags": ["Instancias"],
        "summary": "Obter detalhes de uma instancia",
        "description": "Retorna dados completos da instancia incluindo configuracao e aquecimento. Aceita ID numerico ou codigo alfanumerico.",
        "operationId": "detalhesInstancia",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID numerico ou codigo da instancia" }
        ],
        "responses": {
          "200": {
            "description": "Detalhes da instancia",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/InstanciaDetalhes" },
                "example": {
                  "error": false,
                  "message": "",
                  "data": {
                    "instancia": {
                      "id": 14,
                      "codigo": "INST001",
                      "nome": "Instancia Principal",
                      "public_token": "a1b2c3d4e5f6...",
                      "status": "connected",
                      "tipo_cobranca": "MENSAL",
                      "metadata": { "nome": "Joao Silva", "numero": "5511999999999" },
                      "created_at": "2025-07-01T10:00:00.000000Z",
                      "updated_at": "2025-07-01T10:00:00.000000Z"
                    },
                    "configuracao": {
                      "webhook_url": "https://meusite.com/webhook",
                      "webhook_ativo": true,
                      "config_json": { "rejeitar_chamadas": false }
                    },
                    "aquecimento": null
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/whatsapp/instancia/{id}/status": {
      "get": {
        "tags": ["Instancias"],
        "summary": "Obter status da instancia",
        "operationId": "obterStatusInstancia",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "ID ou codigo da instancia" }
        ],
        "responses": {
          "200": {
            "description": "Status atual",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "",
                  "data": {
                    "status_banco": "connected",
                    "tem_qrcode": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/whatsapp/instancia/{id}/qrcode": {
      "get": {
        "tags": ["Conexao"],
        "summary": "Obter QR Code para conexao",
        "description": "Retorna o QR Code em base64 se disponivel. Se a sessao ja estiver ativa, retorna sessao_ativa=true.",
        "operationId": "obterQRCode",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "QR Code disponivel",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "",
                  "data": {
                    "qrcode": "data:image/png;base64,iVBORw0KGgo...",
                    "sessao_ativa": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "QR Code nao disponivel",
            "content": {
              "application/json": {
                "example": {
                  "error": true,
                  "message": "QR Code nao disponivel",
                  "data": null
                }
              }
            }
          }
        }
      }
    },
    "/whatsapp/instancia/{id}/qrcode/image": {
      "get": {
        "tags": ["Conexao"],
        "summary": "Obter QR Code como imagem JPG",
        "description": "Retorna a imagem do QR Code em formato JPG (Content-Type: image/jpeg). Util para embed direto em <img src>.",
        "operationId": "obterQRCodeImage",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Imagem JPG do QR Code",
            "content": {
              "image/jpeg": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "404": {
            "description": "QR Code nao disponivel",
            "content": {
              "application/json": {
                "example": { "error": true, "message": "QR Code nao disponivel", "data": null }
              }
            }
          }
        }
      }
    },
    "/whatsapp/instancia/{id}/iniciar": {
      "post": {
        "tags": ["Conexao"],
        "summary": "Iniciar sessao WhatsApp",
        "description": "Inicia a sessao no microservico para gerar QR Code. Necessario antes de obter o QR Code. Se ja estiver conectado, retorna erro.",
        "operationId": "iniciarSessao",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Sessao iniciada",
            "content": {
              "application/json": {
                "example": { "error": false, "message": "Sessao iniciada com sucesso", "data": null }
              }
            }
          },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/whatsapp/instancia/{id}/solicitar-pareamento": {
      "post": {
        "tags": ["Conexao"],
        "summary": "Solicitar codigo de pareamento (Pairing Code)",
        "description": "Solicita um codigo de pareamento para conectar via numero de telefone. Limpa credenciais antigas e inicia a sessao automaticamente antes de solicitar o codigo. O codigo expira em 120 segundos. O usuario deve digitar o codigo no WhatsApp do celular: Configuracoes -> Aparelhos conectados -> Conectar com codigo.",
        "operationId": "solicitarPareamento",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "telefone": { "type": "string", "pattern": "^\\d{10,15}$", "example": "5511999999999", "description": "Numero de telefone com DDI+DDD+numero (apenas digitos, 10 a 15)" }
                },
                "required": ["telefone"]
              },
              "example": { "telefone": "5511999999999" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Codigo de pareamento gerado",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "Codigo de pareamento gerado. Digite no WhatsApp do celular: Configuracoes -> Aparelhos conectados -> Conectar com codigo.",
                  "data": {
                    "pairing_code": "W4NQJMRD",
                    "expira_em_segundos": 120
                  }
                }
              }
            }
          },
          "422": { "$ref": "#/components/responses/ValidationError" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/whatsapp/instancia/{id}/codigo-pareamento": {
      "get": {
        "tags": ["Conexao"],
        "summary": "Obter codigo de pareamento atual",
        "description": "Recupera o codigo de pareamento armazenado no Redis. Retorna expirado=true se o codigo nao estiver mais disponivel (TTL 120s).",
        "operationId": "obterCodigoPareamento",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Codigo de pareamento",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "",
                  "data": {
                    "pairing_code": "W4NQJMRD",
                    "expirado": false
                  }
                }
              }
            }
          }
        }
      }
    },
    "/whatsapp/instancia/{id}/importar-sessao": {
      "post": {
        "tags": ["Conexao"],
        "summary": "Importar sessao WhatsApp (WebAuth)",
        "description": "Importa uma sessao WhatsApp exportada pela extensao WhatsApp Session Extractor. A sessao conecta automaticamente apos a importacao (nao precisa chamar /iniciar). O session_data deve ser o JSON completo gerado pela extensao (maximo 512KB).",
        "operationId": "importarSessao",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session_data": { "type": "string", "description": "JSON da sessao exportada (string, maximo 524288 bytes / 512KB)", "example": "{\"identityKey\":{\"private\":\"...\",\"public\":\"...\"},\"account\":{\"details\":\"...\"},\"registrationId\":12345,...}" }
                },
                "required": ["session_data"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sessao importada",
            "content": {
              "application/json": {
                "example": { "error": false, "message": "Sessao importada com sucesso. Aguardando conexao.", "data": null }
              }
            }
          },
          "422": { "$ref": "#/components/responses/ValidationError" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/whatsapp/instancia/{id}/pausar": {
      "post": {
        "tags": ["Conexao"],
        "summary": "Pausar sessao WhatsApp",
        "description": "Fecha a sessao no microservico mantendo as credenciais (tipo=1). A instancia pode ser reiniciada posteriormente.",
        "operationId": "pausarSessao",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Sessao pausada",
            "content": {
              "application/json": {
                "example": { "error": false, "message": "Sessao pausada com sucesso", "data": null }
              }
            }
          }
        }
      }
    },
    "/whatsapp/instancia/{id}/desconectar": {
      "post": {
        "tags": ["Conexao"],
        "summary": "Desconectar instancia",
        "description": "Desconecta a instancia do WhatsApp, remove credenciais (tipo=2) e deleta todas as notificacoes associadas.",
        "operationId": "desconectarInstancia",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Instancia desconectada",
            "content": {
              "application/json": {
                "example": { "error": false, "message": "Instancia desconectada com sucesso", "data": null }
              }
            }
          }
        }
      }
    },
    "/whatsapp/instancia/{id}": {
      "delete": {
        "tags": ["Instancias"],
        "summary": "Deletar instancia",
        "description": "Remove a instancia, suas configuracoes, notificacoes e credenciais permanentemente.",
        "operationId": "deletarInstancia",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Instancia deletada",
            "content": {
              "application/json": {
                "example": { "error": false, "message": "Instancia deletada com sucesso", "data": null }
              }
            }
          }
        }
      }
    },
    "/whatsapp/instancia/verificar-numero": {
      "post": {
        "tags": ["Instancias"],
        "summary": "Verificar se numero possui WhatsApp",
        "description": "Consulta se um numero de telefone possui conta WhatsApp ativa. Resultado cacheado por 1 dia (86400s).",
        "operationId": "verificarNumero",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "instancia": { "type": "string", "nullable": true, "description": "ID da instancia (opcional, usa a primeira se omitido)" }
                },
                "required": ["telefone"]
              },
              "example": { "telefone": "5511999999999", "instancia": "14" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado da verificacao",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "Verificacao realizada com sucesso",
                  "data": {
                    "exists": true,
                    "number": "5511999999999",
                    "cached": false
                  }
                }
              }
            }
          },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/instancia/{id}/foto-perfil": {
      "post": {
        "tags": ["Instancias"],
        "summary": "Obter foto de perfil de um contato",
        "description": "Consulta a foto de perfil de um numero. A instancia deve estar conectada.",
        "operationId": "obterFotoPerfil",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "telefone": { "type": "string", "example": "5511999999999" }
                },
                "required": ["telefone"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Foto de perfil obtida",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "Foto de perfil obtida com sucesso",
                  "data": {
                    "profilePictureUrl": "https://pps.whatsapp.net/v/t61.12345...",
                    "profilePictureBase64": null,
                    "number": "5511999999999"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Instancia nao conectada",
            "content": {
              "application/json": {
                "example": { "error": true, "message": "Instancia nao esta conectada", "data": null }
              }
            }
          }
        }
      }
    },
    "/whatsapp/enviar-mensagem": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar mensagem de texto",
        "description": "Adiciona uma mensagem de texto na fila Redis para processamento assincrono. Se a instancia tiver assinatura (plano free), anexa automaticamente o texto de assinatura.",
        "operationId": "enviarMensagem",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mensagem": { "type": "string", "example": "Ola, tudo bem?" },
                  "telefone": { "type": "string", "example": "5511999999999", "description": "Numero com DDI+DDD+numero ou JID de grupo" },
                  "instancia": { "type": "string", "nullable": true, "description": "ID da instancia (opcional)" }
                },
                "required": ["mensagem", "telefone"]
              },
              "example": { "mensagem": "Ola, tudo bem?", "telefone": "5511999999999", "instancia": "14" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mensagem enfileirada",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/NotificacaoResponse" },
                "example": {
                  "error": false,
                  "message": "",
                  "data": {
                    "notificacao_id": 12345,
                    "message": "Mensagem adicionada na fila para processamento"
                  }
                }
              }
            }
          },
          "422": { "$ref": "#/components/responses/ValidationError" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/whatsapp/enviar-foto": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar imagem via URL",
        "description": "Envia uma imagem a partir de uma URL publica. Requer recurso mensagem_imagem no plano.",
        "operationId": "enviarFoto",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "link": { "type": "string", "format": "uri", "example": "https://exemplo.com/foto.jpg" },
                  "nome": { "type": "string", "example": "foto.jpg" },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["link", "nome", "telefone"]
              },
              "example": { "link": "https://exemplo.com/foto.jpg", "nome": "foto.jpg", "telefone": "5511999999999", "instancia": "14" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Foto enfileirada",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/NotificacaoResponse" },
                "example": { "error": false, "message": "", "data": { "notificacao_id": 12345, "message": "Foto adicionada na fila para processamento" } }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/enviar-foto-64": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar imagem em base64",
        "description": "Envia uma imagem codificada em base64. A imagem e armazenada no S3 antes do envio.",
        "operationId": "enviarFoto64",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "foto_base64": { "type": "string", "description": "Imagem em base64 (sem prefixo data:)", "example": "iVBORw0KGgoAAAANSUhEUg..." },
                  "nome": { "type": "string", "example": "foto" },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["foto_base64", "nome", "telefone"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Foto enfileirada",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/NotificacaoResponse" }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/enviar-arquivo": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar arquivo via URL",
        "description": "Envia um arquivo a partir de uma URL publica. Requer recurso mensagem_arquivo no plano.",
        "operationId": "enviarArquivo",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "link": { "type": "string", "format": "uri", "example": "https://exemplo.com/doc.pdf" },
                  "nome": { "type": "string", "example": "documento.pdf" },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "mensagem": { "type": "string", "nullable": true, "example": "Segue o documento" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["link", "nome", "telefone"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Arquivo enfileirado",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/enviar-arquivo-64": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar arquivo em base64",
        "description": "Envia um arquivo codificado em base64. Valida o tipo MIME real do arquivo contra o tipo_arquivo informado. Tipos suportados: pdf, xml, doc, docx, xls, xlsx, png, jpg, jpeg, gif, csv, txt, zip, rar, mp3, mp4.",
        "operationId": "enviarArquivo64",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "arquivo_base64": { "type": "string", "description": "Arquivo em base64" },
                  "tipo_arquivo": { "type": "string", "example": "pdf", "description": "Extensao do arquivo (pdf, doc, xls, png, etc)" },
                  "nome": { "type": "string", "example": "documento.pdf" },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "mensagem": { "type": "string", "nullable": true },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["arquivo_base64", "tipo_arquivo", "nome", "telefone"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Arquivo enfileirado",
            "content": {
              "application/json": {
                "example": { "error": false, "message": "", "data": { "queue": true, "notificacao_id": 12345, "message": "Arquivo em fila para envio" } }
              }
            }
          },
          "400": {
            "description": "Tipo de arquivo nao suportado ou invalido",
            "content": {
              "application/json": {
                "example": { "error": true, "message": "Tipo de arquivo nao suportado", "data": null }
              }
            }
          },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/enviar-audio": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar audio via URL",
        "description": "Envia um audio a partir de uma URL publica. Aceita MP3 e OGG. MP3 e convertido para OGG automaticamente. Requer recurso mensagem_audio.",
        "operationId": "enviarAudio",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_url": { "type": "string", "format": "uri", "example": "https://exemplo.com/audio.mp3" },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["audio_url", "telefone"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Audio enfileirado", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } } },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/enviar-audio-64": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar audio em base64",
        "description": "Envia um audio codificado em base64. Aceita MP3, OGG e WebM. O audio e convertido para OGG e armazenado no S3 antes do envio.",
        "operationId": "enviarAudio64",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_base64": { "type": "string", "description": "Audio em base64" },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["audio_base64", "telefone"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Audio enfileirado", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } } },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/enviar-video": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar video via URL",
        "description": "Envia um video a partir de uma URL publica. Requer recurso mensagem_video no plano.",
        "operationId": "enviarVideo",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "video_url": { "type": "string", "format": "uri", "example": "https://exemplo.com/video.mp4" },
                  "nome": { "type": "string", "example": "video.mp4" },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "mensagem": { "type": "string", "nullable": true, "example": "Veja este video" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["video_url", "nome", "telefone"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Video enfileirado", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } } },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/enviar-preview": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar mensagem com preview de link",
        "description": "Envia uma mensagem de texto com preview de URL (link preview). Pode incluir imagem, titulo e descricao.",
        "operationId": "enviarPreview",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mensagem": { "type": "string", "example": "Confira este site" },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "url": { "type": "string", "format": "uri", "example": "https://exemplo.com" },
                  "titulo": { "type": "string", "nullable": true, "example": "Exemplo Site" },
                  "descricao": { "type": "string", "nullable": true, "example": "Descricao do site" },
                  "imagem_url": { "type": "string", "format": "uri", "nullable": true },
                  "tipo_imagem": { "type": "string", "enum": ["small", "medium", "large"], "nullable": true, "default": "medium" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["mensagem", "telefone", "url"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Preview enfileirado", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } } },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/enviar-botao": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar mensagem com botao interativo",
        "description": "Envia uma mensagem com botoes interativos. Requer recurso mensagem_botao no plano. Formato flexivel suporta botoes simples, listas e secoes.",
        "operationId": "enviarBotao",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "text": { "type": "string", "nullable": true, "example": "Escolha uma opcao" },
                  "footer": { "type": "string", "nullable": true },
                  "title": { "type": "string", "nullable": true },
                  "subtitle": { "type": "string", "nullable": true },
                  "headerType": { "type": "string", "nullable": true },
                  "image": { "type": "string", "nullable": true },
                  "buttons": { "type": "array", "nullable": true, "items": { "type": "object" } },
                  "sections": { "type": "array", "nullable": true, "items": { "type": "object" } },
                  "buttonText": { "type": "string", "nullable": true },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["telefone"]
              },
              "example": {
                "telefone": "5511999999999",
                "text": "Escolha uma opcao:",
                "footer": "APIFacil",
                "buttons": [
                  { "id": "1", "text": "Sim" },
                  { "id": "2", "text": "Nao" }
                ],
                "instancia": "14"
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Botao enfileirado", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } } },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/enviar-localizacao": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Enviar localizacao",
        "description": "Envia uma localizacao (latitude/longitude) com nome e endereco opcionais.",
        "operationId": "enviarLocalizacao",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "latitude": { "type": "number", "minimum": -90, "maximum": 90, "example": -23.5505 },
                  "longitude": { "type": "number", "minimum": -180, "maximum": 180, "example": -46.6333 },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "nome": { "type": "string", "nullable": true, "maxLength": 255, "example": "Marco Zero SP" },
                  "endereco": { "type": "string", "nullable": true, "maxLength": 500, "example": "Praca da Se, Sao Paulo - SP" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["latitude", "longitude", "telefone"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Localizacao enfileirada", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } } },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/apagar-mensagem": {
      "post": {
        "tags": ["Mensagens"],
        "summary": "Apagar mensagem",
        "description": "Solicita a remocao de uma mensagem enviada. O message_id deve ser o ID retornado pelo WhatsApp apos o envio.",
        "operationId": "apagarMensagem",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "message_id": { "type": "string", "example": "3EB0123456789" },
                  "telefone": { "type": "string", "example": "5511999999999" },
                  "from_me": { "type": "boolean", "default": true, "description": "Se a mensagem foi enviada por voce (true) ou recebida (false)" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["message_id", "telefone"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Solicitacao enfileirada",
            "content": {
              "application/json": {
                "example": { "error": false, "message": "Solicitacao de apagar mensagem enfileirada com sucesso", "data": null }
              }
            }
          },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/grupos": {
      "get": {
        "tags": ["Grupos"],
        "summary": "Listar grupos da instancia",
        "description": "Lista todos os grupos que a instancia participa.",
        "operationId": "listarGrupos",
        "parameters": [
          { "name": "instancia", "in": "query", "schema": { "type": "string" }, "description": "ID da instancia (opcional)" }
        ],
        "responses": {
          "200": {
            "description": "Lista de grupos",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "",
                  "data": [
                    { "id": "120363000000@g.us", "name": "Grupo de Teste", "participants": 10 }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/whatsapp/grupo/enviar-mensagem": {
      "post": {
        "tags": ["Grupos"],
        "summary": "Enviar mensagem para grupo",
        "operationId": "enviarMensagemGrupo",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mensagem": { "type": "string", "example": "Ola grupo!" },
                  "grupo_id": { "type": "string", "example": "120363000000@g.us" },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["mensagem", "grupo_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Mensagem enfileirada", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } } },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/grupo/enviar-arquivo": {
      "post": {
        "tags": ["Grupos"],
        "summary": "Enviar arquivo para grupo",
        "description": "Requer recurso mensagem_arquivo no plano.",
        "operationId": "enviarArquivoGrupo",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "link": { "type": "string", "format": "uri", "example": "https://exemplo.com/doc.pdf" },
                  "nome": { "type": "string", "example": "documento.pdf" },
                  "grupo_id": { "type": "string", "example": "120363000000@g.us" },
                  "mensagem": { "type": "string", "nullable": true },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["link", "nome", "grupo_id"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Arquivo enfileirado", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } } },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/grupo/enviar-preview": {
      "post": {
        "tags": ["Grupos"],
        "summary": "Enviar mensagem com preview para grupo",
        "description": "Requer recurso mensagem_imagem no plano (preview usa imagens).",
        "operationId": "enviarPreviewGrupo",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mensagem": { "type": "string" },
                  "grupo_id": { "type": "string", "example": "120363000000@g.us" },
                  "url": { "type": "string", "format": "uri" },
                  "titulo": { "type": "string", "nullable": true },
                  "descricao": { "type": "string", "nullable": true },
                  "imagem_url": { "type": "string", "format": "uri", "nullable": true },
                  "tipo_imagem": { "type": "string", "enum": ["small", "medium", "large"], "nullable": true },
                  "instancia": { "type": "string", "nullable": true }
                },
                "required": ["mensagem", "grupo_id", "url"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Preview enfileirado", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificacaoResponse" } } } },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/configuracao/{id}": {
      "put": {
        "tags": ["Configuracoes"],
        "summary": "Atualizar configuracao da instancia",
        "description": "Atualiza webhooks e configuracoes da instancia. Webhooks nao estao disponiveis no plano free.",
        "operationId": "updateConfiguration",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "webhook_url": { "type": "string", "format": "uri", "nullable": true },
                  "webhook_status": { "type": "string", "format": "uri", "nullable": true },
                  "webhook_grupo": { "type": "string", "format": "uri", "nullable": true },
                  "webhook_ativo": { "type": "boolean", "nullable": true },
                  "rejeitar_chamadas": { "type": "boolean", "nullable": true },
                  "tipos_envio": { "type": "array", "items": { "type": "string" }, "nullable": true },
                  "ativar_delay_envio_resposta": { "type": "boolean", "nullable": true },
                  "ativar_notificacao_instancia": { "type": "boolean", "nullable": true },
                  "ativar_atualizacoes_interacao": { "type": "boolean", "nullable": true }
                }
              },
              "example": {
                "webhook_url": "https://meusite.com/webhook",
                "webhook_ativo": true,
                "rejeitar_chamadas": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Configuracao atualizada",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "Configuracao atualizada com sucesso",
                  "data": {
                    "id": 1,
                    "instancia_id": 14,
                    "webhook_url": "https://meusite.com/webhook",
                    "webhook_ativo": true,
                    "config_json": { "rejeitar_chamadas": true }
                  }
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" }
        }
      }
    },
    "/whatsapp/notificacoes": {
      "get": {
        "tags": ["Notificacoes"],
        "summary": "Listar notificacoes",
        "description": "Lista notificacoes de envio com filtros opcionais e paginacao.",
        "operationId": "listarNotificacoes",
        "parameters": [
          { "name": "data_inicial", "in": "query", "schema": { "type": "string", "format": "date" }, "description": "Data inicial (YYYY-MM-DD)" },
          { "name": "data_final", "in": "query", "schema": { "type": "string", "format": "date" }, "description": "Data final (YYYY-MM-DD)" },
          { "name": "instancia_id", "in": "query", "schema": { "type": "integer" } },
          { "name": "tipo_envio", "in": "query", "schema": { "type": "string" } },
          { "name": "per_page", "in": "query", "schema": { "type": "integer", "default": 15 } }
        ],
        "responses": {
          "200": {
            "description": "Lista paginada de notificacoes",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "data": {
                    "current_page": 1,
                    "data": [
                      {
                        "id": 12345,
                        "instancia_id": 14,
                        "numero_destino": "5511999999999",
                        "mensagem": "Ola, tudo bem?",
                        "status": "enviado",
                        "enviado": true,
                        "erro": false,
                        "created_at": "2025-07-01T10:00:00.000000Z"
                      }
                    ],
                    "total": 100,
                    "per_page": 15,
                    "last_page": 7
                  }
                }
              }
            }
          }
        }
      }
    },
    "/whatsapp/notificacoes/{id}": {
      "get": {
        "tags": ["Notificacoes"],
        "summary": "Consultar notificacao especifica",
        "description": "Retorna detalhes de uma notificacao incluindo historico de webhook.",
        "operationId": "consultarNotificacao",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "responses": {
          "200": {
            "description": "Detalhes da notificacao",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "data": {
                    "id": 12345,
                    "instancia_id": 14,
                    "numero_destino": "5511999999999",
                    "mensagem": "Ola, tudo bem?",
                    "status": "enviado",
                    "webhook": {
                      "enviado": true,
                      "erro": false,
                      "tentativas": 1,
                      "payloads": [],
                      "respostas": [],
                      "ultima_tentativa": "2025-07-01T10:01:00.000000Z",
                      "proxima_tentativa": null
                    }
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/whatsapp/notificacao/reprocessar-webhook": {
      "post": {
        "tags": ["Notificacoes"],
        "summary": "Reprocessar webhook de uma notificacao",
        "description": "Reenvia o webhook de uma notificacao especifica. O usuario so pode reprocessar suas proprias notificacoes.",
        "operationId": "reprocessarWebhook",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": { "type": "integer", "example": 12345 }
                },
                "required": ["id"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook reprocessado com sucesso",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "Webhook enviado com sucesso",
                  "data": {
                    "notificacao_id": 12345,
                    "webhook_url": "https://meusite.com/webhook",
                    "status_code": 200,
                    "response_body": "OK",
                    "tentativas_totais": 2
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "422": { "$ref": "#/components/responses/ValidationError" },
          "500": {
            "description": "Falha ao enviar webhook",
            "content": {
              "application/json": {
                "example": {
                  "error": true,
                  "message": "Falha ao enviar webhook",
                  "data": {
                    "notificacao_id": 12345,
                    "status_code": 500,
                    "observacao": "O sistema de retry automatico continuara tentando conforme agendado"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/whatsapp/qrcode/{token}": {
      "get": {
        "tags": ["Publico"],
        "summary": "Obter QR Code publico (sem autenticacao)",
        "description": "Endpoint publico sem autenticacao. Retorna o QR Code de uma instancia usando seu public_token.",
        "operationId": "getPublicQrcode",
        "security": [],
        "parameters": [
          { "name": "token", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Public token da instancia" }
        ],
        "responses": {
          "200": {
            "description": "QR Code publico",
            "content": {
              "application/json": {
                "example": {
                  "error": false,
                  "message": "",
                  "data": {
                    "qrcode": "data:image/png;base64,iVBORw0KGgo...",
                    "instance_name": "Instancia Principal",
                    "session_active": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "Instancia ou QR Code nao encontrado",
            "content": {
              "application/json": {
                "example": { "error": true, "message": "QR Code not available", "data": null }
              }
            }
          }
        }
      }
    }
  }
}