wapp-api — callback
Em vez de você consultar de tempos em tempos, nós avisamos: fazemos um
POST numa URL sua. Peça a ativação informando a URL — precisa ser https.
Dois eventos saem pela mesma URL, distinguidos pela chave evento:
evento |
Quando | Ativado |
|---|---|---|
status |
mudou o estado de uma mensagem que você mandou | por padrão |
mensagem_recebida |
alguém mandou mensagem para a sua instância | sob pedido |
Sempre ramifique pelo evento. Podem entrar eventos novos no futuro; um
receptor que assume um formato só quebra quando isso acontecer.
evento status
POST https://seu-sistema.com.br/wapp/callback
Content-Type: application/json; charset=utf-8
X-Wapp-Signature: 9f2b...c41e
{
"evento": "status",
"id": 42,
"status": "entregue",
"numero_destino": "5547999998888",
"instancia": "principal",
"id_mensagem_wa": "3EB0F7BA9660A3BF84D92D",
"erro": null,
"em": "2026-08-28T17:10:00"
}
| Campo | O que é |
|---|---|
id |
o mesmo id que o POST /api/mensagens devolveu |
status |
enviado, entregue, lido ou falhou |
numero_destino |
destino já normalizado |
instancia |
o nome que você deu à instância |
id_mensagem_wa |
id da mensagem no WhatsApp |
erro |
preenchido só quando status é falhou |
em |
quando a mudança foi registrada |
Uma mensagem gera vários avisos ao longo da vida — normalmente
entregue e depois lido. Trate cada um como uma atualização do mesmo
id, não como mensagens diferentes.
evento mensagem_recebida
Chega quando alguém manda mensagem para a sua instância. Formato dos campos
e cuidados de atendimento automático em docs/api-entrada.md; assinatura,
retentativa e idempotência valem igual para os dois eventos.
Confira a assinatura
O corpo vai assinado com HMAC-SHA256 usando um segredo que só você e nós
temos, no header X-Wapp-Signature. Sem conferir, qualquer um que descubra
a URL do seu sistema poderia forjar um "foi entregue".
Assine os bytes crus do corpo, antes de qualquer parse:
import hashlib, hmac
def valido(corpo_bytes, assinatura_recebida, segredo):
esperada = hmac.new(segredo.encode(), corpo_bytes,
hashlib.sha256).hexdigest()
# compare_digest e não ==: comparação comum vaza tempo
return hmac.compare_digest(esperada, assinatura_recebida or '')
<?php
function valido(string $corpo, string $assinatura, string $segredo): bool {
$esperada = hash_hmac('sha256', $corpo, $segredo);
return hash_equals($esperada, $assinatura);
}
O que esperamos da sua resposta
Devolva qualquer 2xx. O corpo é ignorado.
Qualquer outra coisa — 4xx, 5xx, timeout, conexão recusada — conta como falha e nós tentamos de novo:
| Tentativa | Espera |
|---|---|
| 2ª | 1 minuto |
| 3ª | 5 minutos |
| 4ª | 15 minutos |
| 5ª | 1 hora |
Depois da 5ª desistimos daquele aviso. Os seguintes continuam sendo tentados normalmente.
Responda rápido: o timeout é de 10 segundos. Se o seu processamento for demorado, grave e devolva 200 na hora — processe depois.
Cuidados
Seja idempotente. Uma retentativa pode entregar duas vezes o mesmo
aviso, se a primeira chegou mas a resposta se perdeu. Use o par
id + status como chave, e id para mensagem_recebida.
Não confie na ordem. O normal é entregue antes de lido, mas com
retentativa um aviso antigo pode chegar depois. Compare com o status que
você já tem e ignore o que for para trás.
lido pode nunca chegar. Depende de o destinatário abrir a conversa e
de ele não ter desligado a confirmação de leitura. entregue também não vem
quando a mensagem é para o próprio número conectado.