> ## Documentation Index
> Fetch the complete documentation index at: https://laas.mippo.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks de eventos de transação e KYC

> Receba notificações em tempo real de mudanças de status KYC, eventos do ciclo de transação e callbacks de liquidação com payloads assinados de webhook.

A Supercosmos envia requisições `POST` assinadas para a sua URL de webhook quando eventos-chave ocorrem. Sempre verifique a assinatura antes de processar.

## Eventos

| Evento | Quando |
| - | - |
| `transaction.completed` | Stablecoin liquidada on-chain |
| `transaction.failed` | Pagamento expirou ou falhou on-chain |
| `transaction.pix_ready` | QR Pix pronto após verificação de liveness |
| `kyc.approved` | Submissão de KYC aprovada |
| `kyc.rejected` | Submissão de KYC rejeitada |

## Estrutura do payload

```json theme={null}
{
  "event": "transaction.completed",
  "timestamp": "2026-07-01T18:12:44.000Z",
  "data": {
    "transactionId": "tx_1719000000_xyz",
    "txHash": "0xabc123...",
    "asset": "USDT",
    "amount": "90.25",
    "walletAddress": "0xYourUserWalletAddress"
  }
}
```

## Verificação de assinatura

Toda requisição inclui um header `X-Mippo-Signature` — um HMAC-SHA256 do corpo bruto da requisição usando o seu webhook secret.

> [!WARNING]
>
> Sempre verifique a assinatura. Nunca processe eventos de webhook vindos de fontes não verificadas.

```typescript webhook-handler.ts theme={null}
import crypto from 'crypto';

function verifyWebhook(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(signature, 'hex')
  );
}

// Express example
app.post('/webhooks/mippo', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-mippo-signature'] as string;

  if (!verifyWebhook(req.body.toString(), sig, process.env.WEBHOOK_SECRET!)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const { event, data } = JSON.parse(req.body.toString());

  switch (event) {
    case 'transaction.completed':
      // Credit user account, send confirmation email, etc.
      console.log('Settled:', data.txHash);
      break;
    case 'kyc.rejected':
      // Notify user their KYC failed
      break;
  }

  res.sendStatus(200); // Acknowledge within 5 seconds
});
```

> [!NOTE]
>
> Use `express.raw()` (e não `express.json()`) para que o corpo bruto seja preservado para a verificação de assinatura. Fazer o parse do JSON após a verificação é seguro.

## Política de retry

Se o seu endpoint retornar um status diferente de `2xx` ou atingir timeout (5s), a Supercosmos faz novas tentativas com backoff exponencial:

| Tentativa | Intervalo |
| - | - |
| 1ª retry | 1 minuto |
| 2ª retry | 5 minutos |
| 3ª retry | 30 minutos |
| 4ª retry | 2 horas |
| 5ª retry | 6 horas — final |

Após 5 retries com falha, o evento é marcado como `FAILED` e você é notificado por e-mail.

## Rotacionando o seu webhook secret

No [painel do desenvolvedor](https://partners.mippo.io/partner/webhooks), clique em **Rotate secret**. O seu secret antigo permanece válido por **30 minutos** durante a janela de transição.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.