Segurança dos Webhooks
Visão Geral
Todos os webhooks que a 3X Pay envia para a URL de notificação configurada na sua conta são assinados criptograficamente com HMAC-SHA256. A assinatura permite que você confirme, do seu lado, que a requisição:- Foi realmente enviada pela 3X Pay (autenticidade)
- Não foi alterada no caminho (integridade)
- Não é uma reentrega maliciosa de uma notificação antiga (proteção contra replay)
Chave de assinatura
O segredo usado para gerar a assinatura é o seuapi_secret — a mesma credencial
usada para autenticar as chamadas à API. Você a encontra no painel da 3X Pay em
Integrações > Credenciais de API (veja Credenciais de API).
Headers de segurança
Toda requisição de webhook inclui os seguintes headers:| Header | Exemplo | Descrição |
|---|---|---|
X-Webhook-Signature | sha256=9f86d081884c7d65... | Assinatura HMAC-SHA256 em hexadecimal, prefixada por sha256=. |
X-Webhook-Timestamp | 1747526400 | Momento do envio (Unix timestamp, em segundos). Usado no cálculo da assinatura. |
X-Webhook-Event-Id | evt_10293 | Identificador único do evento. Estável entre retentativas — use para idempotência. |
X-Webhook-Attempt | 1 | Número da tentativa de entrega (começa em 1 e incrementa a cada retentativa). |
Como a assinatura é gerada
A 3X Pay monta uma string chamadasigned_payload e calcula o HMAC-SHA256 dela usando
o seu api_secret como chave:
X-Webhook-Signature é sha256= + essa assinatura em hexadecimal.
Como validar (passo a passo)
Verifique o timestamp (anti-replay)
Rejeite a requisição se
X-Webhook-Timestamp estiver fora de uma janela de
tolerância (recomendado: ±5 minutos / 300 segundos) em relação ao horário atual.Recalcule o HMAC
Monte
signed_payload = timestamp + "." + corpo_bruto e calcule
HMAC_SHA256(signed_payload, api_secret) em hexadecimal.Compare em tempo constante
Compare o valor calculado com o recebido em
X-Webhook-Signature (sem o prefixo
sha256=) usando uma função de comparação em tempo constante
(timingSafeEqual, hmac.compare_digest, hash_equals). Nunca use == simples.Exemplos de implementação
Idempotência e retentativas
- Se a sua aplicação não responder com HTTP 2xx, a 3X Pay reenvia o webhook automaticamente: até 5 tentativas, com backoff exponencial (intervalo inicial de ~5 segundos).
- Todas as tentativas do mesmo evento carregam o mesmo
X-Webhook-Event-Id. Persista esse identificador e ignore eventos já processados para evitar processamento duplicado (ex.: creditar o mesmo pagamento duas vezes). - A cada tentativa o
X-Webhook-Timestampé renovado e a assinatura é recalculada. Por isso, valide a assinatura sempre com oX-Webhook-Timestampda própria requisição recebida, não com um valor armazenado.