Webhooks
O Ozzie expõe um endpoint de webhook que recebe mensagens WhatsApp de entrada roteadas através da Evolution API. Quando um usuário envia uma mensagem para sua instância WhatsApp, a Evolution API a encaminha para este endpoint, o Ozzie a processa e responde automaticamente ao usuário no idioma configurado.
Esta é a base para construir um coach financeiro no WhatsApp sem precisar escrever nenhuma lógica de roteamento de mensagens.
Como funciona
Usuário (WhatsApp) → Evolution API → POST /api/webhooks/evolution → Ozzie processa + responde
↓
Usuário recebe resposta no WhatsApp
- Um usuário envia uma mensagem WhatsApp para sua instância Evolution API
- A Evolution API encaminha o payload da mensagem para sua URL de webhook configurada
- O Ozzie verifica a assinatura da requisição, identifica o usuário pelo número de telefone e processa a mensagem
- O Ozzie envia uma resposta automática de volta através da Evolution API no idioma configurado do usuário
POST /api/webhooks/evolution
Este endpoint é chamado pela Evolution API, não pelo seu servidor. Seu trabalho é configurar a Evolution API para apontar para ele. O Ozzie cuida de todo o resto.
Atenção ao caminho: /api/webhooks/evolution — não /v1/.... Este endpoint está fora do namespace REST versionado porque está em conformidade com o contrato de webhook da Evolution API, não com o formato de requisição padrão do Ozzie.
Guia de configuração
Passo 1: Configurar a Evolution API
No dashboard ou configuração da Evolution API, defina a URL do webhook para sua instância como:
https://seu-dominio.com/api/webhooks/evolution
Substitua seu-dominio.com pelo domínio onde seu backend integrado com o Ozzie está hospedado.
A Evolution API só encaminhará eventos de webhook para endpoints HTTPS. O desenvolvimento local requer um túnel (ex.: ngrok, Cloudflare Tunnel ou similar).
Passo 2: Definir o segredo do webhook
Na sua configuração de ambiente, defina:
EVOLUTION_WEBHOOK_SECRET=seu_segredo_compartilhado_aqui
Este deve ser o mesmo valor que você configura na Evolution API como apikey ou segredo de webhook para sua instância. O Ozzie usa isso para verificar que as requisições recebidas são genuinamente da Evolution API e não forjadas.
Passo 3: Registrar seus usuários com seus números de telefone
Para o Ozzie rotear uma mensagem WhatsApp de entrada para o usuário correto, o número de telefone do remetente deve corresponder ao campo phone_e164 de um usuário no Ozzie.
Ao criar usuários que interagirão via WhatsApp, inclua o número de telefone no formato E.164:
curl -X POST https://api.ozzieapp.com/v1/users \
-H "Authorization: Bearer ozp_Y2xpZW50X2ExYjJjM2Q0OnNrX2xpdmVfeEs5bVAycVI3dEwu" \
-H "Content-Type: application/json" \
-d '{
"external_user_id": "user_789",
"name": "Ana Mendes",
"language": "pt",
"phone_e164": "+5511987654321"
}'
Se uma mensagem chegar de um número de telefone que não corresponde a nenhum usuário registrado, o Ozzie retornará 404 para a Evolution API e nenhuma resposta será enviada.
Tipos de mensagem suportados
messageType da Evolution API | O que o usuário envia | Como o Ozzie processa |
|---|---|---|
conversation | Uma mensagem de texto simples | Analisada como mensagem de chat ou registro de transação |
imageMessage | Uma foto (ex.: um recibo) | Processada pelo analisador de imagens do Ozzie para extrair dados de transação |
O parsing de PDF e planilhas está disponível via endpoint REST de transações, mas atualmente não é suportado através do webhook WhatsApp. Para uploads de documentos, direcione seus usuários a uma interface web que chame POST /transactions diretamente.
Formato do payload do webhook
Este é o payload que a Evolution API envia para seu endpoint. O Ozzie analisa este formato automaticamente — você não precisa transformá-lo.
{
"event": "messages.upsert",
"instance": "nome_da_sua_instancia",
"data": {
"key": {
"remoteJid": "5511987654321@s.whatsapp.net",
"fromMe": false,
"id": "3EB0A1B2C3D4E5F6A7B8"
},
"messageType": "conversation",
"message": {
"conversation": "gastei R$45 no supermercado"
}
}
}
Payload de mensagem de imagem
{
"event": "messages.upsert",
"instance": "nome_da_sua_instancia",
"data": {
"key": {
"remoteJid": "5511987654321@s.whatsapp.net",
"fromMe": false,
"id": "3EB0A1B2C3D4E5F6FFFF"
},
"messageType": "imageMessage",
"message": {
"imageMessage": {
"caption": "meu recibo do supermercado",
"mimetype": "image/jpeg",
"url": "https://media.evolution.example.com/media/abc123.jpg"
}
}
}
}
Campos principais
| Campo | Descrição |
|---|---|
data.key.remoteJid | O ID WhatsApp do remetente. O Ozzie remove o sufixo @s.whatsapp.net para obter o número de telefone. |
data.key.fromMe | Se true, esta mensagem foi enviada pela sua instância (saída). O Ozzie ignora mensagens fromMe: true. |
data.messageType | Determina como o Ozzie processa o corpo da mensagem. |
data.message.conversation | O conteúdo de texto (para tipo conversation). |
Segurança
O Ozzie verifica cada requisição de webhook recebida verificando o header apikey contra o valor armazenado na variável de ambiente EVOLUTION_WEBHOOK_SECRET.
POST /api/webhooks/evolution
apikey: seu_segredo_compartilhado_aqui
Content-Type: application/json
Se o header estiver ausente ou o valor não corresponder, o Ozzie retorna 401 Unauthorized e descarta a mensagem.
Boas práticas de segurança
Use um segredo forte e aleatório. Gere pelo menos 32 bytes de dados aleatórios:
openssl rand -hex 32
# ex.: a7f3c8e1b2d4e5f60718293a4b5c6d7e8f901234567890abcdef01234567890
Rotacione segredos periodicamente. Atualize EVOLUTION_WEBHOOK_SECRET e a configuração da Evolution API ao mesmo tempo durante uma janela de baixo tráfego para evitar mensagens perdidas durante a transição.
Use apenas HTTPS. Nunca exponha o endpoint de webhook via HTTP simples em produção. Todo o tráfego de webhook deve ser criptografado em trânsito.
Restrinja o tráfego de entrada por IP (opcional). Se a Evolution API tiver um intervalo de IP de saída fixo para sua instância, configure seu firewall ou proxy reverso para permitir apenas requisições desses IPs.
Respostas automáticas do Ozzie
Quando o Ozzie processa com sucesso uma mensagem de entrada, ele envia uma resposta de volta através da Evolution API automaticamente. A resposta é gerada pelo mesmo coach de IA que POST /chat/messages e é retornada no idioma configurado do usuário.
Exemplo: mensagem de texto recebida → resposta do coach enviada
Usuário envia (WhatsApp):
Acabei de pagar a conta de luz — R$120
Ozzie responde (WhatsApp):
Anotado! Registrei R$120 de Conta de Luz em Utilidades 💡 Seu total em utilidades em maio agora é R$195, o que está dentro do seu orçamento. Você está indo bem este mês — continue assim!
Exemplo: foto de recibo recebida → transação analisada enviada
Usuário envia foto de um recibo de supermercado.
Ozzie responde:
Analisei seu recibo do Supermercado Extra: R$87,40 registrado em Alimentação em 5 de maio. Seu total em alimentação em maio agora é R$302. Você tem cerca de R$98 restantes no orçamento de comida do mês.
Tratamento de usuários desconhecidos
Se uma mensagem WhatsApp chegar de um número de telefone que não corresponde a nenhum usuário registrado:
- O Ozzie retorna
404para a Evolution API - Nenhuma resposta é enviada ao usuário
- O evento é registrado para depuração
Para integrar usuários via WhatsApp, você precisa de um fluxo de cadastro separado. Veja o guia de caso de uso do Bot WhatsApp para uma implementação completa que lida com primeiras mensagens e aciona o cadastro do usuário.
Erros
| Status HTTP | Quando ocorre |
|---|---|
200 OK | Mensagem processada com sucesso — o Ozzie enviou ou enfileirou uma resposta |
401 Unauthorized | O header apikey está ausente ou não corresponde ao EVOLUTION_WEBHOOK_SECRET |
404 Not Found | Nenhum usuário Ozzie encontrado com phone_e164 correspondente |
422 Unprocessable Entity | O payload está malformado ou o messageType não é suportado |
500 Internal Server Error | O processamento falhou — a Evolution API tentará novamente conforme sua configuração |
A Evolution API normalmente tenta novamente entregas de webhook com falha. Certifique-se de que seu endpoint seja idempotente — processar a mesma mensagem duas vezes não deve criar transações duplicadas. O Ozzie deduplica pelo campo id da mensagem da Evolution API.