Os webhooks entregues a Parceiros são assinados com HMAC-SHA256. Valide a assinatura antes de processar qualquer payload para garantir que a requisição veio da Movvia.
A cada entrega de webhook, a Movvia inclui o header X-Movvia-Signature com o HMAC calculado sobre o corpo bruto da requisição usando o segredo compartilhado negociado no onboarding.
X-Movvia-Signature: sha256={hex_do_hmac}- Leia o corpo da requisição como bytes brutos (não faça parse de JSON antes).
- Calcule
HMAC-SHA256(corpo_bytes, segredo). - Compare o resultado (em hex) com o valor de
X-Movvia-Signatureapós o prefixosha256=. - Use comparação em tempo constante (
hmac.compare_digestou equivalente) para evitar timing attacks. - Se os valores coincidirem, processe o evento. Caso contrário, retorne
401e descarte.
import crypto from 'crypto';
function validarAssinatura(
corpo: Buffer,
headerAssinatura: string,
segredo: string,
): boolean {
const esperado = 'sha256=' + crypto
.createHmac('sha256', segredo)
.update(corpo)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(headerAssinatura),
Buffer.from(esperado),
);
}import hmac
import hashlib
def validar_assinatura(corpo: bytes, header_assinatura: str, segredo: str) -> bool:
esperado = 'sha256=' + hmac.new(
segredo.encode(),
corpo,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(header_assinatura, esperado)import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
public boolean validarAssinatura(byte[] corpo, String headerAssinatura, String segredo) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(segredo.getBytes(), "HmacSHA256"));
String esperado = "sha256=" + bytesToHex(mac.doFinal(corpo));
return MessageDigest.isEqual(headerAssinatura.getBytes(), esperado.getBytes());
}Os eventos seguem o padrão pe.<modulo>.<evento>. Exemplos:
| Evento | Descrição |
|---|---|
pe.transacao.recebida | Nova passagem detectada para uma placa cadastrada. |
pe.pedidos.confirmado | Pedido confirmado pelo parceiro. |
pe.pedidos.cancelado | Pedido cancelado. |
O catálogo completo está na Referência da API de Parceiros.
A Movvia retentar a entrega com backoff exponencial por até 24 horas em caso de falha (timeouts ou respostas 5xx). Implemente idempotência no seu receptor para lidar com entregas duplicadas em caso de retentativa.
Veja: Idempotência
Seu endpoint de webhook deve responder com 200 OK dentro de 5 segundos. Processe o evento de forma assíncrona se necessário.