Skip to main content
Toda entrega de webhook leva o header X-Wabox-Signature, calculado com o segredo da instância sobre o corpo cru da requisição:
  • t — timestamp Unix (segundos) de quando o Wabox assinou.
  • v1HMAC-SHA256(secret, "<t>.<corpo cru>") em hexadecimal.
O segredo (whsec_…) aparece no painel em Webhooks e configurações gerais e em GET /webhooks (campo secret). Cada instância tem o seu.

Verificação

1

Leia o corpo cru

A assinatura é sobre os bytes exatos que chegaram. Se o seu framework já converteu o JSON em objeto, re-serializar não reproduz o mesmo texto. Capture o corpo antes do parser (express.raw, request.body() no FastAPI, php://input).
2

Recalcule e compare em tempo constante

Monte "<t>.<corpo>", calcule o HMAC-SHA256 com o segredo e compare com v1 usando comparação de tempo constante.
3

Rejeite timestamps antigos

Descarte entregas com t a mais de 5 minutos do relógio atual. Isso limita ataques de repetição com um corpo capturado.

Rotação do segredo

POST /webhooks/secret gera um segredo novo e devolve o valor. Entregas já enfileiradas continuam assinadas com o segredo anterior até esgotarem as tentativas; aceite os dois por algumas horas durante a troca. Hoje o header traz um único v1=; escreva o verificador aceitando vários, separados por vírgula, para não quebrar se isso mudar.

Quando não há assinatura

Toda instância nasce com um segredo. Se GET /webhooks devolver secret: null (instâncias antigas), as entregas chegam sem o header: gere um segredo com POST /webhooks/secret e passe a exigir a assinatura no seu endpoint.

Outras defesas

  • Use HTTPS na URL do webhook. HTTP é aceito para testes, mas expõe o conteúdo das mensagens no caminho.
  • Trate event_id como chave de idempotência: entregas podem repetir.
  • Não confie em instance_id do corpo para autorizar: use a assinatura da instância correspondente.