# Validação HMAC-SHA256 — Webhooks

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.

## Como funciona

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}
```

## Algoritmo de validação

1. Leia o corpo da requisição como bytes brutos (não faça parse de JSON antes).
2. Calcule `HMAC-SHA256(corpo_bytes, segredo)`.
3. Compare o resultado (em hex) com o valor de `X-Movvia-Signature` após o prefixo `sha256=`.
4. Use comparação em tempo constante (`hmac.compare_digest` ou equivalente) para evitar timing attacks.
5. Se os valores coincidirem, processe o evento. Caso contrário, retorne `401` e descarte.


## Exemplos de validação


```typescript
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),
  );
}
```


```python
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)
```


```java
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());
}
```

## Catálogo de eventos

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](/apis/parceiros/openapi).

## Retry e entrega garantida

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](/compartilhado/seguranca/idempotencia)

Endpoint de recepção
Seu endpoint de webhook deve responder com `200 OK` dentro de 5 segundos. Processe o evento de forma assíncrona se necessário.