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

# Webhooks

> Receba eventos da GoatPay no seu servidor — configuração, eventos, assinatura HMAC e API.

Sua aplicação não precisa consultar `GET /payment-pix/get/:id` em loop. Quando um pagamento confirma, a GoatPay envia um `POST` HTTPS para a URL cadastrada.

## Configurar

<Steps>
  <Step title="1. Endpoint HTTPS">
    Exponha uma rota pública, por exemplo `https://api.suaempresa.com/goatpay/webhook`.
  </Step>

  <Step title="2. Cadastrar URL">
    Via API: [POST /webhooks/create](/api-reference/endpoint/webhooks/create) com sua chave `gp_live_...`.
  </Step>

  <Step title="3. Guardar o segredo">
    Anote o `whsec_...` exibido **uma única vez** na criação.
  </Step>

  <Step title="4. Validar assinatura">
    Confira [Segurança e assinatura](#segurança-e-assinatura) em cada `POST` recebido.
  </Step>
</Steps>

### Escopo por API key

Endpoints criados com `POST /v1/webhooks/create` ficam vinculados à chave usada. Recebem eventos das transações criadas pela **mesma API key**. Endpoints do dashboard (sem vínculo de chave) recebem eventos de toda a conta.

### Teste

Dispare o evento `webhook.test` cadastrando o tipo na lista de `events` e processando um teste a partir do painel da conta, ou aguarde uma transação real da mesma API key.

## Formato da entrega

Cada entrega é um `POST` com corpo JSON no formato abaixo. O campo `event` repete o tipo inscrito no endpoint; `data` carrega o payload do evento.

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "nome.do.evento",
  "createdAt": "2026-05-24T12:00:00.000Z",
  "data": {}
}
```

| Campo       | Descrição                                                                                   |
| ----------- | ------------------------------------------------------------------------------------------- |
| `id`        | ID único da **entrega** — use para idempotência (não confundir com `data.id` da transação). |
| `event`     | Tipo do evento (igual a `x-goatpay-event`).                                                 |
| `createdAt` | Momento em que a entrega foi criada (ISO 8601).                                             |
| `data`      | Payload do evento — formato varia por tipo (veja [Eventos](#eventos)).                      |

O objeto `data` segue o mesmo formato enxuto das respostas `/v1`: sem `provider`, `accountId`, `metadata`, `direction` nem `updatedAt`. IDs do processador aparecem como `referenceId`; infrações MED como `infractionId`.

### Tipos de `data`

| Família               | Eventos                                     | Formato de referência                                                                                                    |
| --------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| PIX recebido          | `payment.*`, `refund.*`                     | [GET /payment-pix/get](/api-reference/endpoint/payment-pix/get), [GET /refunds/get](/api-reference/endpoint/refunds/get) |
| PIX enviado           | `transfer.*` (exceto `transfer.internal.*`) | [GET /transfer-pix/get](/api-reference/endpoint/transfer-pix/get)                                                        |
| Transferência interna | `transfer.internal.*`                       | [GET /transfer-internal/get](/api-reference/endpoint/transfer-internal/get)                                              |
| MED                   | `med.*`                                     | [GET /meds/get](/api-reference/endpoint/meds/get/\{id})                                                                  |
| Link de pagamento     | `payment_link.paid`                         | Objeto de sessão (abaixo)                                                                                                |
| Nota fiscal           | `invoice.*`                                 | Apenas `invoiceId` — consulte o painel ou a API fiscal da conta                                                          |
| Teste                 | `webhook.test`                              | Metadados do disparo manual                                                                                              |

### Campos úteis em transações PIX

| Campo                                      | Quando aparece                                                                          |
| ------------------------------------------ | --------------------------------------------------------------------------------------- |
| `payer`                                    | `payment.paid` de `PIX_IN` — nome e documento do pagador (omitido se não identificado). |
| `recipient`                                | `transfer.completed` de `PIX_OUT` — favorecido confirmado na liquidação.                |
| `copyPaste`, `qrCodeBase64`, `qrcodeUrl`   | `payment.created` — dados do QR gerado.                                                 |
| `expiresAt`                                | Cobrança PIX pendente ou expirada.                                                      |
| `securityReview`                           | `transfer.created` — saque retido para análise antifraude (`pending: true`).            |
| `refund`                                   | Eventos `refund.*` e `payment.refunded` — estado do estorno no depósito original.       |
| `transferKind`, `recipientEmail`, `pairId` | Transferência interna (`INTERNAL_TRANSFER_*`).                                          |

Headers:

```txt theme={null}
Content-Type: application/json
x-goatpay-event: payment.paid
x-goatpay-signature: sha256=<hmac do corpo JSON>
x-goatpay-delivery: <id da entrega>
```

A assinatura é calculada sobre o **raw body** (bytes exatos recebidos), não sobre um objeto re-serializado.

## Segurança e assinatura

Cada entrega usa **HMAC-SHA256** com o segredo `whsec_...` da criação do endpoint.

### Validação (Node.js)

```typescript theme={null}
import crypto from "node:crypto";

export function verifyGoatPayWebhook(
  rawBody: string | Buffer,
  signatureHeader: string | undefined,
  webhookSecret: string,
): boolean {
  if (!signatureHeader?.startsWith("sha256=")) return false;
  const received = signatureHeader.slice("sha256=".length);
  const expected = crypto
    .createHmac("sha256", webhookSecret)
    .update(typeof rawBody === "string" ? rawBody : Buffer.from(rawBody))
    .digest("hex");
  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(received, "hex");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
```

<Warning>
  Use `timingSafeEqual` na comparação. Nunca processe o evento sem validar `x-goatpay-signature`.
</Warning>

### Retentativas

Se o endpoint não responder `2xx` a tempo, a GoatPay reenvia com backoff: **1 min, 5 min, 15 min, 1 h, 4 h** (até **5 tentativas**).

### Idempotência

Persista o `id` da entrega antes de processar. Duplicatas devem responder `200` sem efeito colateral.

```typescript theme={null}
const deliveryId = req.body.id;
if (await alreadyProcessed(deliveryId)) {
  return res.status(200).json({ ok: true });
}
await processEvent(req.body);
await markProcessed(deliveryId);
return res.status(200).json({ ok: true });
```

### Checklist

* URL **HTTPS** em produção
* Validar `x-goatpay-signature` com o `whsec_...` correto
* Responder `200` após processar ou enfileirar com segurança
* Tratar o mesmo `id` de entrega apenas uma vez
* Ignorar campos extras desconhecidos em `data`

## Eventos

Inscreva os tipos abaixo em `events` ao criar o endpoint. Use `"*"` apenas se realmente precisar de todos os eventos futuros.

### Catálogo (ativos)

| Evento                        | Família               |
| ----------------------------- | --------------------- |
| `payment.created`             | PIX recebido          |
| `payment.paid`                | PIX recebido          |
| `payment.failed`              | PIX recebido          |
| `payment.pix.expired`         | PIX recebido          |
| `payment.refunded`            | PIX recebido (legado) |
| `refund.requested`            | Estorno PIX           |
| `refund.completed`            | Estorno PIX           |
| `refund.failed`               | Estorno PIX           |
| `transfer.created`            | PIX enviado           |
| `transfer.completed`          | PIX enviado           |
| `transfer.failed`             | PIX enviado           |
| `transfer.internal.completed` | Transferência interna |
| `transfer.internal.received`  | Transferência interna |
| `med.created`                 | MED                   |
| `med.evidence_sent`           | MED                   |
| `med.updated`                 | MED                   |
| `payment_link.paid`           | Link de pagamento     |
| `invoice.created`             | Nota fiscal           |
| `invoice.processing`          | Nota fiscal           |
| `invoice.issued`              | Nota fiscal           |
| `invoice.failed`              | Nota fiscal           |
| `invoice.cancelled`           | Nota fiscal           |
| `webhook.test`                | Teste                 |

<Note>
  Eventos de **cripto** e **boleto** existem no código mas **não estão ativos** na API pública no momento.
</Note>

### PIX recebido

Disparados por cobranças [POST /payment-pix/create](/api-reference/endpoint/payment-pix/create). Em todos os exemplos, `data.type` é `PIX_IN`.

| Evento                | Quando ocorre                                                    | `data.status` |
| --------------------- | ---------------------------------------------------------------- | ------------- |
| `payment.created`     | QR PIX gerado e aguardando pagamento.                            | `PENDING`     |
| `payment.paid`        | Depósito confirmado no SPI.                                      | `COMPLETED`   |
| `payment.failed`      | Falha no fluxo de recebimento.                                   | `FAILED`      |
| `payment.pix.expired` | QR expirou sem pagamento.                                        | `CANCELED`    |
| `payment.refunded`    | Estorno concluído (legado; mesmo payload de `refund.completed`). | `REVERSED`    |

`payment.created` — inclui QR para exibir ao pagador (`payer` omitido enquanto pendente):

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "payment.created",
  "createdAt": "2026-05-24T11:55:00.000Z",
  "data": {
    "id": "clx_transacao",
    "type": "PIX_IN",
    "status": "PENDING",
    "amount": 100,
    "feeAmount": 0.5,
    "netAmount": 99.5,
    "currency": "BRL",
    "externalReference": "pedido-123",
    "referenceId": "ref_pix_abc",
    "copyPaste": "00020101021226820014br.gov.bcb.pix...",
    "qrCodeBase64": "data:image/png;base64,iVBORw0KGgo...",
    "expiresAt": "2026-05-25T11:55:00.000Z",
    "createdAt": "2026-05-24T11:55:00.000Z"
  }
}
```

`payment.paid` — pagador identificado em `payer`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "payment.paid",
  "createdAt": "2026-05-24T12:00:00.000Z",
  "data": {
    "id": "clx_transacao",
    "type": "PIX_IN",
    "status": "COMPLETED",
    "amount": 100,
    "feeAmount": 0.5,
    "netAmount": 99.5,
    "currency": "BRL",
    "externalReference": "pedido-123",
    "referenceId": "ref_pix_abc",
    "endToEndId": "E12345678202505301234567890123456",
    "payer": {
      "name": "João da Silva",
      "document": "12345678909"
    },
    "completedAt": "2026-05-24T12:00:00.000Z",
    "createdAt": "2026-05-24T11:55:00.000Z"
  }
}
```

`payment.failed`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "payment.failed",
  "createdAt": "2026-05-24T13:00:00.000Z",
  "data": {
    "id": "clx_transacao",
    "type": "PIX_IN",
    "status": "FAILED",
    "amount": 100,
    "feeAmount": 0.5,
    "netAmount": 99.5,
    "currency": "BRL",
    "externalReference": "pedido-123",
    "referenceId": "ref_pix_abc",
    "createdAt": "2026-05-24T11:55:00.000Z"
  }
}
```

`payment.pix.expired`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "payment.pix.expired",
  "createdAt": "2026-05-25T11:55:00.000Z",
  "data": {
    "id": "clx_transacao",
    "type": "PIX_IN",
    "status": "CANCELED",
    "amount": 100,
    "feeAmount": 0.5,
    "netAmount": 99.5,
    "currency": "BRL",
    "externalReference": "pedido-123",
    "referenceId": "ref_pix_abc",
    "expiresAt": "2026-05-25T11:55:00.000Z",
    "createdAt": "2026-05-24T11:55:00.000Z"
  }
}
```

`payment.refunded` — disparado junto com `refund.completed`; prefira `refund.completed` em integrações novas:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "payment.refunded",
  "createdAt": "2026-05-30T16:00:00.000Z",
  "data": {
    "id": "clx_pix_in",
    "type": "PIX_IN",
    "status": "REVERSED",
    "amount": 100,
    "feeAmount": 0.5,
    "netAmount": 99.5,
    "currency": "BRL",
    "externalReference": "pedido-123",
    "referenceId": "ref_pix_abc",
    "endToEndId": "E12345678202505301234567890123456",
    "completedAt": "2026-05-24T12:00:00.000Z",
    "createdAt": "2026-05-24T11:55:00.000Z",
    "refund": {
      "status": "COMPLETED",
      "refundId": "devolucao-pedido-123",
      "requestedAt": "2026-05-30T15:58:00.000Z",
      "completedAt": "2026-05-30T16:00:00.000Z",
      "debitNet": 99.5,
      "depositNet": 99.5,
      "transferFee": 0,
      "nature": "ORIGINAL",
      "description": "Estorno pedido #123"
    }
  }
}
```

### Estorno PIX (depósito recebido)

Disparados após [POST /refunds/create](/api-reference/endpoint/refunds/create). O `data` é o **depósito original** com bloco `refund`.

| Evento             | Quando ocorre                                                 |
| ------------------ | ------------------------------------------------------------- |
| `refund.requested` | Estorno aceito; saldo reservado; aguardando SPI.              |
| `refund.completed` | Devolução confirmada — **também** dispara `payment.refunded`. |
| `refund.failed`    | Estorno não concluído; saldo restaurado.                      |

`refund.requested`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "refund.requested",
  "createdAt": "2026-05-30T15:58:00.000Z",
  "data": {
    "id": "clx_pix_in",
    "type": "PIX_IN",
    "status": "PROCESSING",
    "amount": 100,
    "feeAmount": 0.5,
    "netAmount": 99.5,
    "currency": "BRL",
    "externalReference": "pedido-123",
    "referenceId": "ref_pix_abc",
    "endToEndId": "E12345678202505301234567890123456",
    "completedAt": "2026-05-24T12:00:00.000Z",
    "createdAt": "2026-05-24T11:55:00.000Z",
    "refund": {
      "status": "PROCESSING",
      "refundId": "devolucao-pedido-123",
      "requestedAt": "2026-05-30T15:58:00.000Z",
      "completedAt": null,
      "debitNet": 99.5,
      "depositNet": 99.5,
      "transferFee": 0,
      "nature": "ORIGINAL",
      "description": "Estorno pedido #123"
    }
  }
}
```

`refund.completed`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "refund.completed",
  "createdAt": "2026-05-30T16:00:00.000Z",
  "data": {
    "id": "clx_pix_in",
    "type": "PIX_IN",
    "status": "REVERSED",
    "amount": 100,
    "feeAmount": 0.5,
    "netAmount": 99.5,
    "currency": "BRL",
    "externalReference": "pedido-123",
    "referenceId": "ref_pix_abc",
    "endToEndId": "E12345678202505301234567890123456",
    "completedAt": "2026-05-24T12:00:00.000Z",
    "createdAt": "2026-05-24T11:55:00.000Z",
    "refund": {
      "status": "COMPLETED",
      "refundId": "devolucao-pedido-123",
      "requestedAt": "2026-05-30T15:58:00.000Z",
      "completedAt": "2026-05-30T16:00:00.000Z",
      "debitNet": 99.5,
      "depositNet": 99.5,
      "transferFee": 0,
      "nature": "ORIGINAL",
      "description": "Estorno pedido #123"
    }
  }
}
```

`refund.failed`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "refund.failed",
  "createdAt": "2026-05-30T15:59:00.000Z",
  "data": {
    "id": "clx_pix_in",
    "type": "PIX_IN",
    "status": "COMPLETED",
    "amount": 100,
    "feeAmount": 0.5,
    "netAmount": 99.5,
    "currency": "BRL",
    "externalReference": "pedido-123",
    "referenceId": "ref_pix_abc",
    "endToEndId": "E12345678202505301234567890123456",
    "completedAt": "2026-05-24T12:00:00.000Z",
    "createdAt": "2026-05-24T11:55:00.000Z",
    "refund": {
      "status": "AVAILABLE",
      "refundId": "devolucao-pedido-123",
      "requestedAt": "2026-05-30T15:58:00.000Z",
      "completedAt": null,
      "debitNet": null,
      "depositNet": null,
      "transferFee": null,
      "nature": "ORIGINAL",
      "description": "Estorno pedido #123"
    }
  }
}
```

### PIX enviado

Disparados por [POST /transfer-pix/create](/api-reference/endpoint/transfer-pix/create). Em todos os exemplos, `data.type` é `PIX_OUT`.

| Evento               | Quando ocorre                              | `data.status`            |
| -------------------- | ------------------------------------------ | ------------------------ |
| `transfer.created`   | Saída registrada (pendente ou em análise). | `PENDING` / `PROCESSING` |
| `transfer.completed` | PIX liquidado no favorecido.               | `COMPLETED`              |
| `transfer.failed`    | Falha, cancelamento ou expiração.          | `FAILED` / `CANCELED`    |

`transfer.created` — `recipient` omitido até liquidar; pode incluir `securityReview`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "transfer.created",
  "createdAt": "2026-06-01T13:00:00.000Z",
  "data": {
    "id": "clx_transacao",
    "type": "PIX_OUT",
    "status": "PROCESSING",
    "amount": 50,
    "feeAmount": 2,
    "netAmount": 52,
    "currency": "BRL",
    "externalReference": "saque-123",
    "referenceId": "ref_out_xyz",
    "pixKey": "12345678909",
    "pixKeyType": "CPF",
    "createdAt": "2026-06-01T13:00:00.000Z",
    "securityReview": {
      "pending": true,
      "maxHours": 24,
      "message": "Sua transferência será aprovada pela equipe. Se levar mais de 30 minutos, contate o suporte."
    }
  }
}
```

`transfer.completed` — `recipient` preenchido após liquidação:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "transfer.completed",
  "createdAt": "2026-06-01T13:05:00.000Z",
  "data": {
    "id": "clx_transacao",
    "type": "PIX_OUT",
    "status": "COMPLETED",
    "amount": 50,
    "feeAmount": 2,
    "netAmount": 52,
    "currency": "BRL",
    "externalReference": "saque-123",
    "referenceId": "ref_out_xyz",
    "endToEndId": "E12345678202505301234567890123456",
    "pixKey": "12345678909",
    "pixKeyType": "CPF",
    "recipient": {
      "name": "Maria Recebedora",
      "document": "12345678909"
    },
    "completedAt": "2026-06-01T13:05:00.000Z",
    "createdAt": "2026-06-01T13:00:00.000Z"
  }
}
```

`transfer.failed`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "transfer.failed",
  "createdAt": "2026-06-01T13:10:00.000Z",
  "data": {
    "id": "clx_transacao",
    "type": "PIX_OUT",
    "status": "FAILED",
    "amount": 50,
    "feeAmount": 2,
    "netAmount": 52,
    "currency": "BRL",
    "externalReference": "saque-123",
    "referenceId": "ref_out_xyz",
    "pixKey": "12345678909",
    "pixKeyType": "CPF",
    "createdAt": "2026-06-01T13:00:00.000Z"
  }
}
```

### Transferência interna

Disparados por [POST /transfer-internal/create](/api-reference/endpoint/transfer-internal/create). Dois eventos por operação:

| Evento                        | Conta   | `data.type`             |
| ----------------------------- | ------- | ----------------------- |
| `transfer.internal.completed` | Origem  | `INTERNAL_TRANSFER_OUT` |
| `transfer.internal.received`  | Destino | `INTERNAL_TRANSFER_IN`  |

`transfer.internal.completed`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "transfer.internal.completed",
  "createdAt": "2026-06-03T10:00:00.000Z",
  "data": {
    "id": "clx_out",
    "type": "INTERNAL_TRANSFER_OUT",
    "status": "COMPLETED",
    "amount": 100,
    "feeAmount": 0,
    "netAmount": 100,
    "currency": "BRL",
    "externalReference": "repasse-parceiro",
    "transferKind": "internal",
    "recipientEmail": "destino@empresa.com",
    "recipientName": "Empresa Destino",
    "pairId": "pair_abc",
    "completedAt": "2026-06-03T10:00:00.000Z",
    "createdAt": "2026-06-03T10:00:00.000Z"
  }
}
```

`transfer.internal.received`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "transfer.internal.received",
  "createdAt": "2026-06-03T10:00:00.000Z",
  "data": {
    "id": "clx_in",
    "type": "INTERNAL_TRANSFER_IN",
    "status": "COMPLETED",
    "amount": 100,
    "feeAmount": 0,
    "netAmount": 100,
    "currency": "BRL",
    "transferKind": "internal",
    "counterpartyName": "Empresa Origem",
    "pairId": "pair_abc",
    "completedAt": "2026-06-03T10:00:00.000Z",
    "createdAt": "2026-06-03T10:00:00.000Z"
  }
}
```

<Note>
  `transfer.internal.received` vai para endpoints da **conta destino**, não da API key que originou o envio.
</Note>

### MED

Disputas **MED** no trilho **PADRAO** (PIX regulado). O objeto `data` segue o mesmo formato de [GET /meds/get](/api-reference/endpoint/meds/get/\{id}).

| Evento              | Quando ocorre                                                                                                      |
| ------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `med.created`       | Nova disputa aberta; saldo bloqueado. Status `OPEN`.                                                               |
| `med.evidence_sent` | Defesa enviada via [POST /meds/evidence](/api-reference/endpoint/meds/evidence); status passa para `UNDER_REVIEW`. |
| `med.updated`       | Resultado final: `ACCEPTED`, `REJECTED`, `CANCELED` ou `EXPIRED`.                                                  |

Exemplo `med.created`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "med.created",
  "createdAt": "2026-05-28T12:00:00.000Z",
  "data": {
    "id": "clx_med",
    "protocol": "MED-123",
    "transactionId": "clx_pix_in",
    "status": "OPEN",
    "amount": 99.9,
    "currency": "BRL",
    "reason": "Não reconhecimento da transação",
    "infractionId": "inf_abc",
    "endToEndId": "E12345678202505281234567890123456",
    "openedAt": "2026-05-28T12:00:00.000Z",
    "dueAt": "2026-06-04T12:00:00.000Z",
    "resolvedAt": null
  }
}
```

Exemplo `med.evidence_sent`:

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "med.evidence_sent",
  "createdAt": "2026-05-29T14:30:00.000Z",
  "data": {
    "id": "clx_med",
    "protocol": "MED-123",
    "transactionId": "clx_pix_in",
    "status": "UNDER_REVIEW",
    "amount": 99.9,
    "currency": "BRL",
    "reason": "Não reconhecimento da transação",
    "infractionId": "inf_abc",
    "endToEndId": "E12345678202505281234567890123456",
    "openedAt": "2026-05-28T12:00:00.000Z",
    "dueAt": "2026-06-04T12:00:00.000Z",
    "resolvedAt": null
  }
}
```

Exemplo `med.updated` (disputa rejeitada — saldo liberado):

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "med.updated",
  "createdAt": "2026-06-02T10:00:00.000Z",
  "data": {
    "id": "clx_med",
    "protocol": "MED-123",
    "transactionId": "clx_pix_in",
    "status": "REJECTED",
    "amount": 99.9,
    "currency": "BRL",
    "reason": "Não reconhecimento da transação",
    "infractionId": "inf_abc",
    "endToEndId": "E12345678202505281234567890123456",
    "openedAt": "2026-05-28T12:00:00.000Z",
    "dueAt": "2026-06-04T12:00:00.000Z",
    "resolvedAt": "2026-06-02T10:00:00.000Z"
  }
}
```

### Links de pagamento

| Evento              | Quando ocorre                      |
| ------------------- | ---------------------------------- |
| `payment_link.paid` | Checkout de link confirmado (PIX). |

`payment_link.paid` — payload próprio (não é `PIX_IN`):

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "payment_link.paid",
  "createdAt": "2026-06-02T15:00:00.000Z",
  "data": {
    "sessionId": "clx_session",
    "status": "PAID",
    "method": "PIX",
    "amount": 99.9,
    "feeAmount": 5.15,
    "netAmount": 94.75,
    "currency": "BRL",
    "transactionId": "clx_tx",
    "externalReference": "pedido-42",
    "paidAt": "2026-06-02T15:00:00.000Z",
    "payer": {
      "name": "Maria",
      "document": "12345678909",
      "email": "maria@email.com",
      "phone": "11999999999"
    },
    "paymentLink": {
      "id": "clx_link",
      "name": "Plano Pro",
      "slug": "plano-pro",
      "publicCode": "abc12"
    }
  }
}
```

Para links pagos via PIX, `payment.paid` também pode ser emitido (formato de [PIX recebido](#pix-recebido)). Para checkout de link, inscreva-se em **`payment_link.paid`**.

### Nota fiscal

Emitidos quando a cobrança usa `emitFiscalInvoice: true` e a emissão automática está ativa. O webhook traz apenas o ID.

| Evento               | Quando ocorre                    |
| -------------------- | -------------------------------- |
| `invoice.created`    | Nota enfileirada após pagamento. |
| `invoice.processing` | Em processamento no emissor.     |
| `invoice.issued`     | Nota emitida.                    |
| `invoice.failed`     | Falha ou rejeição.               |
| `invoice.cancelled`  | Nota cancelada.                  |

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "invoice.issued",
  "createdAt": "2026-06-02T15:01:00.000Z",
  "data": {
    "invoiceId": "clx_invoice"
  }
}
```

### Teste

| Evento         | Quando ocorre                |
| -------------- | ---------------------------- |
| `webhook.test` | Disparo manual no dashboard. |

```json theme={null}
{
  "id": "clxxx_delivery",
  "event": "webhook.test",
  "createdAt": "2026-06-10T18:00:00.000Z",
  "data": {
    "message": "Evento de teste GoatPay",
    "endpointId": "clx_webhook",
    "timestamp": "2026-06-10T18:00:00.000Z"
  }
}
```

### Fluxos comuns

```mermaid theme={null}
sequenceDiagram
  participant API as Sua API
  participant GP as GoatPay
  participant Pagador

  API->>GP: POST /payment-pix/create
  GP->>API: payment.created
  Pagador->>GP: Paga QR PIX
  GP->>API: payment.paid
  API->>API: Libera pedido

  Note over API,GP: Estorno
  API->>GP: POST /refunds/create
  GP->>API: refund.requested
  GP->>API: refund.completed + payment.refunded

  Note over API,GP: MED
  GP->>API: med.created
  API->>GP: POST /meds/evidence
  GP->>API: med.evidence_sent
  GP->>API: med.updated
```

## Endpoints da API

| Ação      | Rota                                                                    |
| --------- | ----------------------------------------------------------------------- |
| Criar     | [POST /webhooks/create](/api-reference/endpoint/webhooks/create)        |
| Listar    | [GET /webhooks/list](/api-reference/endpoint/webhooks/list)             |
| Consultar | [GET /webhooks/get/{id}](/api-reference/endpoint/webhooks/get)          |
| Atualizar | [PATCH /webhooks/update/{id}](/api-reference/endpoint/webhooks/update)  |
| Revogar   | [DELETE /webhooks/delete/{id}](/api-reference/endpoint/webhooks/delete) |

Permissões na API key: `webhooks/create`, `webhooks/list`, `webhooks/get`, `webhooks/update`, `webhooks/delete`.
