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

# Webhooks

> Receba notificações em tempo real sobre eventos de pagamento

## Visão Geral

Webhooks permitem que você receba notificações HTTP automáticas quando eventos importantes acontecem na sua conta, como pagamentos confirmados, reembolsos processados ou saques concluídos.

## Eventos Disponíveis

| Evento                   | Descrição                                                                                      |
| ------------------------ | ---------------------------------------------------------------------------------------------- |
| `payment_completed`      | Pagamento foi confirmado com sucesso                                                           |
| `payment_expired`        | Pagamento expirou sem confirmação                                                              |
| `payment_failed`         | Pagamento recebido mas recusado — depósito bloqueado por política da conta (ex.: pagador CNPJ) |
| `refund_completed`       | Reembolso foi processado                                                                       |
| `withdrawal_completed`   | Saque foi processado com sucesso                                                               |
| `withdrawal_failed`      | Saque foi rejeitado ou falhou                                                                  |
| `withdrawal_reversed`    | Saque foi estornado pelo PSP                                                                   |
| `balance_block_created`  | Bloqueio de saldo criado (MED/judicial/administrativo)                                         |
| `balance_block_approved` | Bloqueio aprovado — valor devolvido ao pagador                                                 |
| `balance_block_rejected` | Bloqueio rejeitado — valor retorna ao lojista                                                  |

## Estrutura do Payload

Todos os webhooks seguem a mesma estrutura base:

```json theme={null}
{
  "event": "payment_completed",
  "eventId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
  "timestamp": "2026-01-11T19:03:28.280Z",
  "subAccount": null,
  "data": {
    // Dados específicos do evento
  }
}
```

| Campo        | Tipo           | Descrição                                                                                  |
| ------------ | -------------- | ------------------------------------------------------------------------------------------ |
| `event`      | string         | Tipo do evento                                                                             |
| `eventId`    | string         | ID único do evento (geralmente o ID da transação)                                          |
| `timestamp`  | string         | Data/hora do evento em formato ISO 8601                                                    |
| `subAccount` | string ou null | `reference` da subconta que originou o evento; `null` quando o evento é da conta principal |
| `data`       | object         | Dados específicos do evento                                                                |

## Subcontas

Quando o evento pertence a uma [subconta](/#subcontas), o campo `subAccount` traz o `reference` dela:

```json theme={null}
{
  "event": "payment_completed",
  "eventId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
  "timestamp": "2026-01-11T19:03:28.280Z",
  "subAccount": "loja-centro",
  "data": {
    "transactionId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
    "amount": 100.21,
    "status": "completed"
  }
}
```

<Warning>
  **Se a subconta não tiver um endpoint de webhook próprio cadastrado, os eventos dela são entregues nos endpoints da conta principal.** É por isso que o `subAccount` é essencial: é ele que diz de qual carteira é o evento.

  Sempre use esse campo para creditar o evento na carteira certa — nunca assuma que todo evento recebido no endpoint da conta principal pertence à conta principal.
</Warning>

## Headers Enviados

Cada requisição de webhook inclui os seguintes headers:

| Header                | Descrição                                            |
| --------------------- | ---------------------------------------------------- |
| `Content-Type`        | `application/json`                                   |
| `User-Agent`          | `Jetpag-Webhook/1.0`                                 |
| `X-Jetpag-Event`      | Tipo do evento (ex.: `payment_completed`)            |
| `X-Jetpag-Webhook-ID` | ID único desta entrega (UUID)                        |
| `X-Jetpag-Signature`  | Assinatura do payload: `sha256=<HMAC-SHA256 em hex>` |
| `X-Jetpag-Timestamp`  | Timestamp da entrega em milliseconds (Unix epoch)    |

## Validando a Assinatura

Cada webhook é assinado com HMAC-SHA256 usando o **secret do seu endpoint**
(exibido uma única vez na criação). Siga estes passos para validar:

1. Calcule o **HMAC-SHA256** do body cru da requisição usando o seu secret como chave
2. Prefixe o resultado em hex com `sha256=`
3. Compare com o header `X-Jetpag-Signature` usando comparação em tempo constante

```typescript Node.js (crypto) theme={null}
import { createHmac, timingSafeEqual } from 'node:crypto';

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-jetpag-signature'] as string; // "sha256=<hex>"
  const rawBody = req.body; // raw string body

  // 1. HMAC-SHA256 do payload com o SEU secret (não hasheie o secret)
  // 2. Prefixar com "sha256="
  const expected = `sha256=${createHmac('sha256', 'seu_webhook_secret')
    .update(rawBody)
    .digest('hex')}`;

  // 3. Comparar em tempo constante
  const isValid =
    typeof signature === 'string' &&
    signature.length === expected.length &&
    timingSafeEqual(Buffer.from(expected), Buffer.from(signature));

  if (!isValid) {
    return res.status(401).send('Assinatura inválida');
  }

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

<Warning>
  Sempre use comparação em tempo constante (`timingSafeEqual`) para evitar ataques de timing.
  Nunca compare assinaturas com `===`.
</Warning>

## Exemplos de Payload

### payment\_completed

Enviado quando um pagamento PIX é confirmado.

```json theme={null}
{
  "event": "payment_completed",
  "eventId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
  "timestamp": "2026-01-11T19:03:28.280Z",
  "data": {
    "transactionId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
    "environment": "sandbox",
    "amount": 100.21,
    "feeAmount": 0.5,
    "netAmount": 99.71,
    "split": [
      { "subAccount": "loja-sul", "amount": 20.00 }
    ],
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "completed",
    "completedAt": "2026-01-11T19:03:28.277Z",
    "externalReference": "pedido-12345",
    "e2eId": "E18189547202603160145ZYFfVx3jP8D",
    "counterpartName": "Maria Silva",
    "counterpartDocument": "12345678900",
    "metadata": {
      "orderId": "ORDER-12345",
      "customerId": "CUST-67890"
    }
  }
}
```

<Note>
  **O `split` do webhook é o que foi efetivamente distribuído**, não o que você pediu na criação da cobrança. Os dois divergem quando a taxa da conta muda entre a cobrança e o pagamento: o líquido encolhe e as pernas são reduzidas na ordem em que foram enviadas, em vez de a liquidação falhar.

  Para conciliar com o extrato da carteira, use sempre o valor que vem no webhook — nunca o que você mandou no request. O campo só aparece quando houve rateio; cobrança sem split não ganha a chave.
</Note>

| Campo                 | Tipo   | Descrição                                                                                                                                                                                                |
| --------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transactionId`       | string | ID único da transação                                                                                                                                                                                    |
| `environment`         | string | Ambiente (`production` ou `sandbox`)                                                                                                                                                                     |
| `amount`              | number | Valor total do pagamento                                                                                                                                                                                 |
| `feeAmount`           | number | Taxa cobrada                                                                                                                                                                                             |
| `netAmount`           | number | Valor líquido (amount - feeAmount)                                                                                                                                                                       |
| `split`               | array  | Rateio efetivado entre as carteiras, em reais; `subAccount` traz o `reference` de destino, ou `principal` para a conta principal (opcional — presente apenas quando houve [split](/#split-de-pagamento)) |
| `currency`            | string | Moeda (BRL)                                                                                                                                                                                              |
| `paymentMethod`       | string | Método de pagamento (pix)                                                                                                                                                                                |
| `status`              | string | Status do pagamento (completed)                                                                                                                                                                          |
| `completedAt`         | string | Data/hora da conclusão em ISO 8601                                                                                                                                                                       |
| `externalReference`   | string | Sua referência externa (opcional)                                                                                                                                                                        |
| `e2eId`               | string | ID fim-a-fim da rede PIX (opcional, presente quando disponível)                                                                                                                                          |
| `counterpartName`     | string | Nome do pagador conforme retornado pelo PSP (opcional)                                                                                                                                                   |
| `counterpartDocument` | string | CPF/CNPJ do pagador conforme retornado pelo PSP (opcional, sem máscara)                                                                                                                                  |
| `metadata`            | object | Metadados customizados enviados na criação do pagamento (opcional)                                                                                                                                       |

### payment\_expired

Enviado quando um pagamento PIX expira sem confirmação.

```json theme={null}
{
  "event": "payment_expired",
  "eventId": "payment_expired_d5e6f7a8-1234-5678-9abc-def012345678",
  "timestamp": "2026-01-11T19:30:00.000Z",
  "data": {
    "transactionId": "d5e6f7a8-1234-5678-9abc-def012345678",
    "environment": "sandbox",
    "amount": 75.50,
    "feeAmount": 0,
    "netAmount": 0,
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "expired",
    "expiredAt": "2026-01-11T19:30:00.000Z",
    "externalReference": "pedido-12345",
    "metadata": {
      "orderId": "ORDER-12345",
      "customerId": "CUST-67890"
    }
  }
}
```

| Campo               | Tipo   | Descrição                                                          |
| ------------------- | ------ | ------------------------------------------------------------------ |
| `transactionId`     | string | ID único da transação                                              |
| `environment`       | string | Ambiente (`production` ou `sandbox`)                               |
| `amount`            | number | Valor do pagamento                                                 |
| `feeAmount`         | number | Taxa cobrada (sempre 0 para pagamentos expirados)                  |
| `netAmount`         | number | Valor líquido (sempre 0 para pagamentos expirados)                 |
| `currency`          | string | Moeda (BRL)                                                        |
| `paymentMethod`     | string | Método de pagamento (pix)                                          |
| `status`            | string | Status do pagamento (expired)                                      |
| `expiredAt`         | string | Data/hora da expiração em ISO 8601                                 |
| `externalReference` | string | Sua referência externa (opcional)                                  |
| `metadata`          | object | Metadados customizados enviados na criação do pagamento (opcional) |

### payment\_failed

Enviado quando um pagamento PIX foi **recebido mas não pôde ser creditado** — hoje, quando a conta bloqueia depósitos de pagadores pessoa jurídica (CNPJ). O valor não entra no seu saldo, não gera taxa e é devolvido ao pagador automaticamente. `blockedDeposit.refund` informa o andamento da devolução.

```json theme={null}
{
  "event": "payment_failed",
  "eventId": "payment_failed_13e3ffd1-55d9-4863-9cc1-8955475cdf64",
  "timestamp": "2026-09-09T20:50:17.612Z",
  "data": {
    "transactionId": "13e3ffd1-55d9-4863-9cc1-8955475cdf64",
    "environment": "production",
    "amount": 5000.00,
    "feeAmount": 0,
    "netAmount": 5000.00,
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "failed",
    "failureReason": "Bloqueio de depósito: pagador CNPJ não permitido",
    "failedAt": "2026-09-09T20:50:17.610Z",
    "createdAt": "2026-09-09T20:49:41.506Z",
    "e2eId": "E71328769202609092049JcZwvkhgNGJ",
    "counterpartName": "EMPRESA PAGADORA LTDA",
    "counterpartDocument": "60937487000165",
    "blockedDeposit": {
      "reason": "cnpj_payer_not_allowed",
      "refund": {
        "status": "confirmed",
        "e2eId": null,
        "settledAt": "2026-09-09T20:50:14.900Z"
      }
    },
    "externalReference": "pedido-12345",
    "metadata": {
      "orderId": "ORDER-12345"
    }
  }
}
```

<Note>
  A devolução é feita pela instituição de pagamento logo após o bloqueio. O `refund.status` do webhook é o estado no momento do envio; o E2E da devolução (`refund.e2eId`) costuma chegar segundos depois — consulte `GET /transactions/{id}` para o dado final e para responder ao pagador.
</Note>

| Campo                             | Tipo   | Descrição                                                                                                             |
| --------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------- |
| `transactionId`                   | string | ID único da transação                                                                                                 |
| `environment`                     | string | Ambiente (`production` ou `sandbox`)                                                                                  |
| `amount`                          | number | Valor pago pelo pagador                                                                                               |
| `feeAmount`                       | number | Taxa cobrada (sempre 0 — nada foi creditado)                                                                          |
| `netAmount`                       | number | Igual a `amount` (referência; nada foi creditado)                                                                     |
| `currency`                        | string | Moeda (BRL)                                                                                                           |
| `paymentMethod`                   | string | Método de pagamento (pix)                                                                                             |
| `status`                          | string | Status do pagamento (failed)                                                                                          |
| `failureReason`                   | string | Motivo, em texto                                                                                                      |
| `failedAt`                        | string | Data/hora da recusa em ISO 8601                                                                                       |
| `createdAt`                       | string | Data/hora da criação da cobrança em ISO 8601                                                                          |
| `e2eId`                           | string | ID fim-a-fim do PIX recebido (opcional)                                                                               |
| `counterpartName`                 | string | Nome do pagador conforme retornado pelo PSP (opcional)                                                                |
| `counterpartDocument`             | string | CNPJ do pagador, sem máscara                                                                                          |
| `blockedDeposit.reason`           | string | Motivo do bloqueio: `cnpj_payer_not_allowed`                                                                          |
| `blockedDeposit.refund.status`    | string | Devolução ao pagador: `pending` (aceita, sem confirmação), `confirmed` (liquidada) ou `failed` (em tratamento manual) |
| `blockedDeposit.refund.e2eId`     | string | ID fim-a-fim da devolução (`D…`), quando já conhecido                                                                 |
| `blockedDeposit.refund.settledAt` | string | Data/hora da liquidação da devolução em ISO 8601, quando confirmada                                                   |
| `externalReference`               | string | Sua referência externa (opcional)                                                                                     |
| `customer`                        | object | Dados do cliente informados na criação da cobrança (opcional)                                                         |
| `metadata`                        | object | Metadados customizados enviados na criação do pagamento (opcional)                                                    |

### refund\_completed

Enviado quando um reembolso é processado.

```json theme={null}
{
  "event": "refund_completed",
  "eventId": "c92d45e6-8b33-4f12-a789-2e56f8901def",
  "timestamp": "2026-01-11T19:22:15.456Z",
  "data": {
    "refundTransactionId": "c92d45e6-8b33-4f12-a789-2e56f8901def",
    "originalTransactionId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
    "environment": "sandbox",
    "amount": 50.00,
    "feeAmount": 0.25,
    "netAmount": 50.00,
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "completed",
    "refundedAt": "2026-01-11T19:22:15.400Z",
    "externalReference": "pedido-12345",
    "metadata": {
      "orderId": "ORDER-12345",
      "customerId": "CUST-67890"
    }
  }
}
```

<Note>
  **Convenção do `netAmount` em refund**: representa o que o destinatário do evento (o cliente final) efetivamente recebe — ou seja, o valor cheio do reembolso. A taxa de reembolso é debitada separadamente do saldo do lojista. O custo total do refund para o lojista é `amount + feeAmount`.
</Note>

| Campo                   | Tipo   | Descrição                                                    |
| ----------------------- | ------ | ------------------------------------------------------------ |
| `refundTransactionId`   | string | ID único da transação de reembolso                           |
| `originalTransactionId` | string | ID da transação original que foi reembolsada                 |
| `environment`           | string | Ambiente (`production` ou `sandbox`)                         |
| `amount`                | number | Valor do reembolso                                           |
| `feeAmount`             | number | Taxa do reembolso cobrada do lojista                         |
| `netAmount`             | number | Valor líquido recebido pelo cliente final (igual a `amount`) |
| `currency`              | string | Moeda (BRL)                                                  |
| `paymentMethod`         | string | Método de pagamento da transação original                    |
| `status`                | string | Status do reembolso (completed)                              |
| `refundedAt`            | string | Data/hora do reembolso em ISO 8601                           |
| `externalReference`     | string | Sua referência externa do pagamento original (opcional)      |
| `metadata`              | object | Metadados customizados do pagamento original (opcional)      |

### withdrawal\_completed

Enviado quando um saque é processado com sucesso.

```json theme={null}
{
  "event": "withdrawal_completed",
  "eventId": "e73775b5-70ee-4bad-be4c-4acff9890e27",
  "timestamp": "2026-01-11T19:08:21.953Z",
  "data": {
    "withdrawalId": "e73775b5-70ee-4bad-be4c-4acff9890e27",
    "projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "environment": "sandbox",
    "amount": 500.00,
    "feeAmount": 2.50,
    "netAmount": 497.50,
    "currency": "BRL",
    "status": "completed",
    "completedAt": "2026-01-11T19:08:21.939Z",
    "externalReference": "saque-empresa-001",
    "e2eId": "E18189547202603160145ZYFfVx3jP8D",
    "counterpartName": "João da Silva",
    "counterpartDocument": "12345678900",
    "metadata": {
      "batchId": "BATCH-001"
    }
  }
}
```

| Campo                 | Tipo   | Descrição                                                                               |
| --------------------- | ------ | --------------------------------------------------------------------------------------- |
| `withdrawalId`        | string | ID único do saque                                                                       |
| `projectId`           | string | ID do projeto do saque (null quando não informado na criação e a conta tem 2+ projetos) |
| `environment`         | string | Ambiente (`production` ou `sandbox`)                                                    |
| `amount`              | number | Valor do saque                                                                          |
| `feeAmount`           | number | Taxa do saque                                                                           |
| `netAmount`           | number | Valor líquido transferido                                                               |
| `currency`            | string | Moeda (BRL)                                                                             |
| `status`              | string | Status do saque (completed)                                                             |
| `completedAt`         | string | Data/hora da conclusão em ISO 8601                                                      |
| `externalReference`   | string | Sua referência externa enviada na criação do saque (opcional)                           |
| `e2eId`               | string | ID fim-a-fim da rede PIX (opcional, presente após confirmação do PSP)                   |
| `counterpartName`     | string | Nome do destinatário no banco de destino (opcional)                                     |
| `counterpartDocument` | string | CPF/CNPJ do destinatário (opcional, sem máscara)                                        |
| `metadata`            | object | Metadados customizados do saque (opcional)                                              |

### withdrawal\_failed

Enviado quando um saque é rejeitado ou falha.

```json theme={null}
{
  "event": "withdrawal_failed",
  "eventId": "b84f12c3-9a21-4e67-bc88-1d45f6789abc",
  "timestamp": "2026-01-11T19:15:42.123Z",
  "data": {
    "withdrawalId": "b84f12c3-9a21-4e67-bc88-1d45f6789abc",
    "projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "environment": "sandbox",
    "amount": 1000.00,
    "feeAmount": 5.00,
    "netAmount": 995.00,
    "currency": "BRL",
    "status": "failed",
    "failedAt": "2026-01-11T19:15:42.100Z",
    "failureReason": "insufficient_funds",
    "externalReference": "saque-empresa-001",
    "e2eId": "E18189547202603160145ZYFfVx3jP8D",
    "counterpartName": "João da Silva",
    "counterpartDocument": "12345678900",
    "metadata": {
      "batchId": "BATCH-001"
    }
  }
}
```

| Campo                 | Tipo   | Descrição                                                                                        |
| --------------------- | ------ | ------------------------------------------------------------------------------------------------ |
| `withdrawalId`        | string | ID único do saque                                                                                |
| `projectId`           | string | ID do projeto do saque (null quando não informado na criação e a conta tem 2+ projetos)          |
| `environment`         | string | Ambiente (`production` ou `sandbox`)                                                             |
| `amount`              | number | Valor do saque                                                                                   |
| `feeAmount`           | number | Taxa do saque                                                                                    |
| `netAmount`           | number | Valor líquido que seria transferido                                                              |
| `currency`            | string | Moeda (BRL)                                                                                      |
| `status`              | string | Status do saque (failed)                                                                         |
| `failedAt`            | string | Data/hora da falha em ISO 8601                                                                   |
| `failureReason`       | string | Motivo da falha (insufficient\_funds, invalid\_account, etc.)                                    |
| `externalReference`   | string | Sua referência externa enviada na criação do saque (opcional)                                    |
| `e2eId`               | string | ID fim-a-fim da rede PIX (opcional, presente apenas se o saque chegou a ser processado pelo PSP) |
| `counterpartName`     | string | Nome do destinatário no banco de destino (opcional)                                              |
| `counterpartDocument` | string | CPF/CNPJ do destinatário (opcional, sem máscara)                                                 |
| `metadata`            | object | Metadados customizados do saque (opcional)                                                       |

### withdrawal\_reversed

Enviado quando um saque é estornado pelo PSP.

```json theme={null}
{
  "event": "withdrawal_reversed",
  "eventId": "f12a34b5-6c78-9d01-ef23-456789abcdef",
  "timestamp": "2026-01-11T20:00:00.000Z",
  "data": {
    "reversalTransactionId": "f12a34b5-6c78-9d01-ef23-456789abcdef",
    "originalTransactionId": "e73775b5-70ee-4bad-be4c-4acff9890e27",
    "environment": "sandbox",
    "amount": 500.00,
    "feeAmount": 0,
    "netAmount": 500.00,
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "completed",
    "reversedAt": "2026-01-11T20:00:00.000Z",
    "metadata": {
      "batchId": "BATCH-001"
    }
  }
}
```

| Campo                   | Tipo   | Descrição                                           |
| ----------------------- | ------ | --------------------------------------------------- |
| `reversalTransactionId` | string | ID único da transação de estorno                    |
| `originalTransactionId` | string | ID do saque original que foi estornado              |
| `environment`           | string | Ambiente (`production` ou `sandbox`)                |
| `amount`                | number | Valor do estorno                                    |
| `feeAmount`             | number | Taxa do estorno                                     |
| `netAmount`             | number | Valor líquido do estorno                            |
| `currency`              | string | Moeda (BRL)                                         |
| `paymentMethod`         | string | Método de pagamento (pix)                           |
| `status`                | string | Status do estorno (completed)                       |
| `reversedAt`            | string | Data/hora do estorno em ISO 8601                    |
| `externalReference`     | string | Sua referência externa do saque original (opcional) |
| `metadata`              | object | Metadados customizados do saque original (opcional) |

### balance\_block\_created

Enviado quando um bloqueio de saldo é criado (MED, judicial ou administrativo).

```json theme={null}
{
  "event": "balance_block_created",
  "eventId": "d4e5f6a7-8b9c-0d1e-2f3a-456789abcdef",
  "timestamp": "2026-01-11T19:30:00.000Z",
  "data": {
    "blockId": "d4e5f6a7-8b9c-0d1e-2f3a-456789abcdef",
    "transactionId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
    "environment": "production",
    "amount": 1500.00,
    "currency": "BRL",
    "blockType": "med",
    "referenceNumber": "MED-2026-001234",
    "reason": "Notificação de infração Pix recebida",
    "status": "awaiting_response",
    "createdAt": "2026-01-11T19:30:00.000Z",
    "externalReference": "pedido-12345",
    "e2eId": "E18189547202603160145ZYFfVx3jP8D"
  }
}
```

| Campo               | Tipo   | Descrição                                                 |
| ------------------- | ------ | --------------------------------------------------------- |
| `blockId`           | string | ID único do bloqueio                                      |
| `transactionId`     | string | ID da transação original bloqueada                        |
| `environment`       | string | Ambiente (`production` ou `sandbox`)                      |
| `amount`            | number | Valor bloqueado em reais                                  |
| `currency`          | string | Moeda (BRL)                                               |
| `blockType`         | string | Tipo do bloqueio (`med`, `judicial` ou `administrative`)  |
| `referenceNumber`   | string | Número de referência do bloqueio                          |
| `reason`            | string | Motivo do bloqueio                                        |
| `status`            | string | Status inicial (`awaiting_response`)                      |
| `createdAt`         | string | Data/hora da criação em ISO 8601                          |
| `externalReference` | string | Referência externa da transação original (opcional)       |
| `e2eId`             | string | ID fim-a-fim da rede PIX da transação original (opcional) |

### balance\_block\_approved

Enviado quando um bloqueio de saldo é aprovado e o valor é devolvido ao pagador original.

```json theme={null}
{
  "event": "balance_block_approved",
  "eventId": "d4e5f6a7-8b9c-0d1e-2f3a-456789abcdef",
  "timestamp": "2026-01-12T14:00:00.000Z",
  "data": {
    "blockId": "d4e5f6a7-8b9c-0d1e-2f3a-456789abcdef",
    "transactionId": "a0b78f10-c7f4-4f5d-98dd-3e36eafeb812",
    "environment": "production",
    "amount": 1500.00,
    "currency": "BRL",
    "blockType": "med",
    "referenceNumber": "MED-2026-001234",
    "reason": "Notificação de infração Pix recebida",
    "resolutionReason": "Devolução confirmada pelo BACEN",
    "status": "approved",
    "createdAt": "2026-01-11T19:30:00.000Z",
    "resolvedAt": "2026-01-12T14:00:00.000Z",
    "externalReference": "pedido-12345",
    "e2eId": "E18189547202603160145ZYFfVx3jP8D"
  }
}
```

| Campo               | Tipo   | Descrição                                                 |
| ------------------- | ------ | --------------------------------------------------------- |
| `blockId`           | string | ID único do bloqueio                                      |
| `transactionId`     | string | ID da transação original bloqueada                        |
| `environment`       | string | Ambiente (`production` ou `sandbox`)                      |
| `amount`            | number | Valor bloqueado em reais                                  |
| `currency`          | string | Moeda (BRL)                                               |
| `blockType`         | string | Tipo do bloqueio (`med`, `judicial` ou `administrative`)  |
| `referenceNumber`   | string | Número de referência do bloqueio                          |
| `reason`            | string | Motivo original do bloqueio                               |
| `resolutionReason`  | string | Motivo da resolução (opcional)                            |
| `status`            | string | Status do bloqueio (`approved`)                           |
| `createdAt`         | string | Data/hora da criação em ISO 8601                          |
| `resolvedAt`        | string | Data/hora da resolução em ISO 8601                        |
| `externalReference` | string | Referência externa da transação original (opcional)       |
| `e2eId`             | string | ID fim-a-fim da rede PIX da transação original (opcional) |

### balance\_block\_rejected

Enviado quando um bloqueio de saldo é rejeitado e o valor retorna ao saldo disponível do lojista.

```json theme={null}
{
  "event": "balance_block_rejected",
  "eventId": "e5f6a7b8-9c0d-1e2f-3a4b-567890abcdef",
  "timestamp": "2026-01-12T14:00:00.000Z",
  "data": {
    "blockId": "e5f6a7b8-9c0d-1e2f-3a4b-567890abcdef",
    "transactionId": "b1c89f20-d8e5-5f6a-99ee-4f47eafeb923",
    "environment": "production",
    "amount": 250.00,
    "currency": "BRL",
    "blockType": "med",
    "referenceNumber": "MED-2026-005678",
    "reason": "Notificação de infração Pix recebida",
    "resolutionReason": "Defesa aceita - transação legítima comprovada",
    "status": "rejected",
    "createdAt": "2026-01-11T19:30:00.000Z",
    "resolvedAt": "2026-01-12T14:00:00.000Z",
    "externalReference": "pedido-67890",
    "e2eId": "E4071059520260316020613919677838"
  }
}
```

| Campo               | Tipo   | Descrição                                                 |
| ------------------- | ------ | --------------------------------------------------------- |
| `blockId`           | string | ID único do bloqueio                                      |
| `transactionId`     | string | ID da transação original bloqueada                        |
| `environment`       | string | Ambiente (`production` ou `sandbox`)                      |
| `amount`            | number | Valor bloqueado em reais                                  |
| `currency`          | string | Moeda (BRL)                                               |
| `blockType`         | string | Tipo do bloqueio (`med`, `judicial` ou `administrative`)  |
| `referenceNumber`   | string | Número de referência do bloqueio                          |
| `reason`            | string | Motivo original do bloqueio                               |
| `resolutionReason`  | string | Motivo da resolução (opcional)                            |
| `status`            | string | Status do bloqueio (`rejected`)                           |
| `createdAt`         | string | Data/hora da criação em ISO 8601                          |
| `resolvedAt`        | string | Data/hora da resolução em ISO 8601                        |
| `externalReference` | string | Referência externa da transação original (opcional)       |
| `e2eId`             | string | ID fim-a-fim da rede PIX da transação original (opcional) |

## Boas Práticas

<AccordionGroup>
  <Accordion title="Responda rapidamente">
    Retorne um status `200 OK` o mais rápido possível. Processe o webhook de forma assíncrona se necessário.
  </Accordion>

  <Accordion title="Implemente idempotência">
    Use o `eventId` para evitar processar o mesmo evento duas vezes. Webhooks podem ser reenviados em caso de falha.
  </Accordion>

  <Accordion title="Use HTTPS">
    Configure seu endpoint apenas com HTTPS para garantir a segurança dos dados.
  </Accordion>
</AccordionGroup>

## Retentativas

Se o seu endpoint não responder com status `2xx`, tentaremos reenviar o webhook:

* **5 tentativas** com backoff exponencial
* Intervalo inicial: 2 segundos
* Intervalo máximo: \~30 segundos entre tentativas

Após 5 tentativas sem sucesso, o webhook é marcado como falho.
