Pular para o conteúdo principal

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
  1. Um usuário envia uma mensagem WhatsApp para sua instância Evolution API
  2. A Evolution API encaminha o payload da mensagem para sua URL de webhook configurada
  3. O Ozzie verifica a assinatura da requisição, identifica o usuário pelo número de telefone e processa a mensagem
  4. 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.

informação

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.

aviso

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 APIO que o usuário enviaComo o Ozzie processa
conversationUma mensagem de texto simplesAnalisada como mensagem de chat ou registro de transação
imageMessageUma foto (ex.: um recibo)Processada pelo analisador de imagens do Ozzie para extrair dados de transação
informaçã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

CampoDescrição
data.key.remoteJidO ID WhatsApp do remetente. O Ozzie remove o sufixo @s.whatsapp.net para obter o número de telefone.
data.key.fromMeSe true, esta mensagem foi enviada pela sua instância (saída). O Ozzie ignora mensagens fromMe: true.
data.messageTypeDetermina como o Ozzie processa o corpo da mensagem.
data.message.conversationO 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 404 para 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 HTTPQuando ocorre
200 OKMensagem processada com sucesso — o Ozzie enviou ou enfileirou uma resposta
401 UnauthorizedO header apikey está ausente ou não corresponde ao EVOLUTION_WEBHOOK_SECRET
404 Not FoundNenhum usuário Ozzie encontrado com phone_e164 correspondente
422 Unprocessable EntityO payload está malformado ou o messageType não é suportado
500 Internal Server ErrorO processamento falhou — a Evolution API tentará novamente conforme sua configuração
dica

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.