# Webhooks

A Movvia entrega eventos em tempo real via HTTP POST no endpoint que você registrar. Todos os payloads são assinados com HMAC-SHA256.

## Estrutura do evento


```json
{
  "evento": "pe.transacao.recebida",
  "versao": "2",
  "id": "evt_8f3a1b2c",
  "timestamp": "2026-04-24T10:00:00Z",
  "parceiroId": "par_7f3a1b2c",
  "dados": {
    "transacaoId": "t_9f2c7e1a",
    "placa": "ABC1D23",
    "valor": 12.50,
    "praca": "KM 245 — Imigrantes",
    "criadoEm": "2026-04-24T09:58:00Z"
  }
}
```

## Catálogo de eventos

| Evento | Quando ocorre |
|  --- | --- |
| `pe.transacao.recebida` | Nova passagem capturada para uma placa monitorada |
| `pe.transacao.atualizada` | Valor ou status de uma passagem foi revisado |
| `pe.transacao.cancelada` | Passagem cancelada pelo EC |
| `pe.pedidos.confirmado` | Pedido confirmado com sucesso |
| `pe.pedidos.cancelado` | Pedido cancelado |
| `pe.pedidos.expirado` | Pedido expirou sem confirmação (48h) |


## Verificar a assinatura HMAC-SHA256

O header `x-movvia-signature` contém a assinatura do payload. Sempre verifique antes de processar.


```typescript
import crypto from 'crypto';

function verificarAssinatura(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// No seu handler:
app.post('/webhook', (req, res) => {
  const assinatura = req.headers['x-movvia-signature'] as string;
  const payload = JSON.stringify(req.body);

  if (!verificarAssinatura(payload, assinatura, process.env.MV_WEBHOOK_SECRET!)) {
    return res.status(401).send('Assinatura inválida');
  }

  // processar evento
  res.status(200).send('OK');
});
```


```python
import hashlib, hmac, os

def verificar_assinatura(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(), payload, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)
```

Tutorial completo em [Validar HMAC](/parceiros/tutorials/validar-hmac).

## Retentativas

A Movvia faz retry automático em caso de falha (status != 2xx ou timeout):

| Tentativa | Intervalo |
|  --- | --- |
| 1ª (original) | — |
| 2ª | 1 min |
| 3ª | 5 min |
| 4ª | 30 min |
| 5ª | 2h |
| 6ª | 6h |
| 7ª | 24h |


Após 7 tentativas sem sucesso, o evento é marcado como `falha_definitiva` e um alerta é enviado por email.

## Requisitos do endpoint

- Responder em até **5 segundos** com status 2xx.
- Processar de forma idempotente — o mesmo evento pode ser entregue mais de uma vez.
- Aceitar `Content-Type: application/json`.
- HTTPS obrigatório em produção.


Processar de forma assíncrona
Responda 200 imediatamente e processe o evento em background. Não faça operações lentas (banco, chamadas externas) dentro do handler síncrono.

## Registrar o endpoint

O endpoint de webhook é configurado no onboarding. Para alterar, entre em contato com [comercial@movvia.com.br](mailto:comercial@movvia.com.br).