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

# Receber eventos

> Cadastre um endpoint, verifique a assinatura HMAC e processe eventos da sua conta

Webhooks notificam o seu sistema quando algo acontece na sua conta iuzypay: a plataforma envia um `POST` com o evento em JSON para uma URL sua, assinado com um segredo que só vocês dois conhecem.

## Cadastrar um endpoint

No dashboard, acesse **Configurações → Webhooks** e cadastre a URL do seu endpoint (HTTPS). Na criação você escolhe quais eventos quer receber — um endpoint **sem seleção recebe todos**.

<Warning>
  O segredo de assinatura (`whsec_...`) é exibido **uma única vez**, na criação do endpoint. Guarde-o com o mesmo cuidado de uma senha: é ele que permite verificar que um evento veio mesmo da iuzypay.
</Warning>

Use o botão **Testar** do dashboard para receber um evento `webhook.test` na hora e validar a integração de ponta a ponta antes de qualquer evento real.

## Anatomia de uma entrega

Cada entrega é um `POST` com corpo JSON neste envelope:

```json theme={null}
{
  "id": "3f2a1b0c-9d8e-4f7a-b6c5-d4e3f2a1b0c9",
  "type": "webhook.test",
  "created_at": "2026-07-06T14:32:00Z",
  "data": {
    "message": "Evento de teste do iuzypay."
  }
}
```

O formato de `data` depende do `type`. Campos novos podem ser adicionados a qualquer momento — ignore o que não conhecer.

### Headers

| Header             | Conteúdo                                               |
| ------------------ | ------------------------------------------------------ |
| `X-Iuzy-Signature` | Assinatura do corpo, no formato `sha256=<hex>`         |
| `X-Iuzy-Event`     | O `type` do evento (ex.: `order.paid`)                 |
| `X-Iuzy-Delivery`  | ID único da entrega — o mesmo em todas as retentativas |
| `X-Iuzy-Timestamp` | Instante de criação da entrega (Unix, segundos)        |
| `User-Agent`       | `iuzypay-webhooks/1`                                   |

## Verificar a assinatura

A assinatura é o **HMAC-SHA256 do corpo cru da requisição**, usando o segredo `whsec_...` como chave, codificado em hexadecimal. Calcule o HMAC do lado de lá e compare com o header em **tempo constante**:

<CodeGroup>
  ```javascript Node.js theme={null}
  import { createHmac, timingSafeEqual } from "node:crypto";

  // rawBody: Buffer com o corpo EXATO da requisição, antes de qualquer parse
  function verifySignature(rawBody, signatureHeader, secret) {
    const expected =
      "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
    const a = Buffer.from(signatureHeader ?? "");
    const b = Buffer.from(expected);
    return a.length === b.length && timingSafeEqual(a, b);
  }

  // Exemplo com Express: use express.raw() na rota do webhook,
  // senão o body chega re-serializado e a assinatura não bate.
  app.post("/webhooks/iuzypay", express.raw({ type: "*/*" }), (req, res) => {
    if (!verifySignature(req.body, req.get("X-Iuzy-Signature"), process.env.IUZYPAY_WEBHOOK_SECRET)) {
      return res.status(401).end();
    }
    res.status(200).end(); // confirme já; processe depois
    const event = JSON.parse(req.body);
    // ...
  });
  ```

  ```php PHP theme={null}
  <?php
  $secret = getenv('IUZYPAY_WEBHOOK_SECRET');
  $rawBody = file_get_contents('php://input');
  $header = $_SERVER['HTTP_X_IUZY_SIGNATURE'] ?? '';

  $expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);

  if (!hash_equals($expected, $header)) {
      http_response_code(401);
      exit;
  }

  http_response_code(200); // confirme já; processe depois
  $event = json_decode($rawBody, true);
  // ...
  ```
</CodeGroup>

<Warning>
  Calcule o HMAC sobre os **bytes crus** do corpo. Fazer parse do JSON e re-serializar muda a ordem das chaves e os espaços — e a assinatura deixa de bater.
</Warning>

O header `X-Iuzy-Timestamp` é informativo (momento em que a entrega foi criada); a assinatura cobre apenas o corpo. Para proteção contra reprocessamento, use a idempotência por ID descrita abaixo.

## Confirmação e retentativas

A iuzypay considera a entrega bem-sucedida quando seu endpoint responde **2xx**. Qualquer outra resposta — ou timeout — agenda uma nova tentativa com espera exponencial:

* Até **6 tentativas** por entrega, com intervalos de 30 s, 1 min, 2 min, 4 min e 8 min (\~15 minutos no total).
* Esgotadas as tentativas, a entrega é marcada como **falha** — o histórico fica visível no dashboard, em **Configurações → Webhooks → entregas**.
* Endpoint desativado no dashboard para de receber na hora, inclusive retentativas pendentes.

Para não estourar o timeout: **responda 2xx imediatamente e processe o evento de forma assíncrona** (fila, job). Validar a assinatura e enfileirar é rápido; o processamento pesado não deve segurar a resposta.

### Idempotência

Uma retentativa reenvia exatamente o mesmo corpo — mesmo `id` de evento e mesmo `X-Iuzy-Delivery`. Se o seu endpoint respondeu 2xx mas a resposta se perdeu na rede, você receberá o evento de novo. Guarde os `id` já processados e ignore repetições.

## Catálogo de eventos

| Evento                  | Descrição                                    | Status     |
| ----------------------- | -------------------------------------------- | ---------- |
| `webhook.test`          | Disparado pelo botão **Testar** do dashboard | Disponível |
| `order.paid`            | Pedido pago                                  | Em breve   |
| `order.refunded`        | Pedido reembolsado                           | Em breve   |
| `order.chargeback`      | Chargeback recebido                          | Em breve   |
| `subscription.created`  | Assinatura criada                            | Em breve   |
| `subscription.canceled` | Assinatura cancelada                         | Em breve   |

<Info>
  Os eventos de pedido e assinatura passam a ser emitidos junto com o lançamento do checkout com pagamento. O contrato de entrega e assinatura documentado nesta página já é o definitivo — a integração que você validar hoje com `webhook.test` continua valendo.
</Info>
