# Formato do evento

URL: https://staging.pagpolar.com/docs/webhooks/formato-do-evento

> Leia o envelope do webhook e cada bloco de data em eventos de venda e de assinatura.

## A requisição que chega

A PagPolar envia um `POST` para a URL do webhook com:

| Header            | Valor                                                                                                                                      |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `Content-Type`    | `application/json`                                                                                                                         |
| `Authorization`   | `Bearer ` seguido do token do webhook. Veja [Autenticar as requisições recebidas](/docs/webhooks/autenticar-requisicoes#token-do-webhook). |
| `X-PagPolar-Test` | `true`, **só** nos envios de teste do [Playground](/docs/webhooks/playground). Os eventos reais não trazem este header.                    |

## Envelope

Todo evento tem o mesmo envelope:

| Campo           | Tipo                | O que é                                                                                                                                                                           |
| --------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`            | texto (uuid)        | Id **desta tentativa** de entrega. [Não serve para descartar repetidos](/docs/webhooks/processar-sem-duplicar#id-do-envelope).                                                    |
| `event`         | texto               | Nome do evento, como `TRANSACTION_PAID`.                                                                                                                                          |
| `creation_date` | texto (data e hora) | Quando esta tentativa foi montada, em UTC.                                                                                                                                        |
| `version`       | texto               | Versão do formato. Hoje é `1.0.0`.                                                                                                                                                |
| `test`          | booleano            | Só aparece, com `true`, nos envios de teste do [Playground](/docs/webhooks/playground) Os eventos reais não trazem o campo. Em produção, ignore qualquer evento com `test: true`. |
| `data`          | objeto              | Os dados do evento.                                                                                                                                                               |

## Exemplo de evento de venda

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "event": "TRANSACTION_PAID",
  "creation_date": "2026-09-15T14:35:05.000Z",
  "version": "1.0.0",
  "data": {
    "transaction": {
      "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "identifier": "PPO0087103960",
      "status": "PAID",
      "type": "BILLING",
      "payment_method": "PIX",
      "total_amount": "97.0000",
      "net_amount": 97,
      "effective_value": "91.1800",
      "base_tax": "5.8200",
      "installment_tax": "0.0000",
      "base_fixed_tax": "0.9900",
      "base_percentage_tax": "4.8300",
      "installments": 1,
      "cycle": 1,
      "paid_at": "2026-09-15T14:35:00.000Z",
      "created_at": "2026-09-15T14:00:00.000Z"
    },
    "items": [
      {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "quantity": 1,
        "amount": "97.0000",
        "original_amount": "97.0000",
        "discount_value": "0.0000",
        "product": {
          "id": "c4d5e6f7-a8b9-4c0d-1e2f-3a4b5c6d7e8f",
          "name": "Curso de exemplo",
          "type": "DIGITAL"
        },
        "price": {
          "id": "d5e6f7a8-b9c0-4d1e-2f3a-4b5c6d7e8f9a",
          "title": "Oferta de lançamento",
          "price": "97.0000",
          "identifier": "PPP1234567890"
        }
      }
    ],
    "product": {
      "id": "c4d5e6f7-a8b9-4c0d-1e2f-3a4b5c6d7e8f",
      "name": "Curso de exemplo",
      "type": "DIGITAL"
    },
    "buyer": {
      "name": "Maria Silva",
      "email": "cliente@exemplo.com",
      "document": "<CPF_DO_CLIENTE>",
      "phone": "<TELEFONE_DO_CLIENTE>"
    },
    "address": null,
    "payment_details": {
      "origin": "DIRECT",
      "qr_code": "00020126580014br.gov.bcb.pix0136a1b2c3d4-e5f6-4a7b-8c9d",
      "billet_barcode": null,
      "billet_link": null,
      "last_credit_card_digits": null,
      "shipping_value": null
    },
    "coupon": null,
    "subscription": null,
    "affiliate": null,
    "source": {
      "channel": "API",
      "api_credential_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
    }
  }
}
```

Os exemplos de cada evento estão no [Catálogo de eventos](/docs/webhooks/eventos).

## Blocos dos eventos de venda

Os eventos que começam com `TRANSACTION_` trazem estes blocos em `data`:

| Bloco                   | O que traz                                                                           |
| ----------------------- | ------------------------------------------------------------------------------------ |
| `transaction`           | A venda.                                                                             |
| `items`                 | Os itens da venda, com produto e oferta.                                             |
| `product`               | O produto principal da venda. Pode vir `null`.                                       |
| `buyer`                 | O cliente. Pode vir `null`.                                                          |
| `address`               | O endereço informado na compra. Pode vir `null`.                                     |
| `payment_details`       | Dados do pagamento: QR Code, boleto e final do cartão. Pode vir `null`.              |
| `coupon`                | O cupom usado. `null` sem cupom.                                                     |
| `subscription`          | Resumo da assinatura, quando a venda é de uma assinatura. Senão, `null`.             |
| `affiliate`             | O afiliado que indicou a venda. `null` sem afiliado. Veja [`affiliate`](#affiliate). |
| `source`                | O canal em que a venda nasceu.                                                       |
| `order_bumps`           | Só aparece em alguns casos. Veja [Order bumps e upsells](#order-bumps-e-upsells).    |
| `reference_transaction` | Só aparece em alguns casos. Veja [Order bumps e upsells](#order-bumps-e-upsells).    |

### `transaction`

| Campo                 | O que é                                                                                                                                            |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                  | Id da venda. Use para ligar ao seu pedido e para consultar `GET /sales/{identifier}`.                                                              |
| `identifier`          | Código da venda: `PPO` seguido de 10 dígitos, que podem começar com zero, como `PPO0087103960`. É o mesmo código das respostas da API e do painel. |
| `status`              | Status da venda [no momento do envio](#estado-no-envio). Veja [Ciclo de vida da venda](/docs/guias/conceitos/ciclo-de-vida-da-venda).              |
| `type`                | Tipo da venda. `BILLING` é a cobrança ao cliente.                                                                                                  |
| `payment_method`      | Meio de pagamento, como `PIX`, `BOLETO` ou `CREDIT_CARD`.                                                                                          |
| `total_amount`        | Valor pago pelo cliente, **com** juros do parcelamento.                                                                                            |
| `net_amount`          | Valor da venda **sem** juros do parcelamento (`total_amount` menos `installment_tax`). É o valor indicado para conciliação.                        |
| `effective_value`     | Valor que fica para você, depois da taxa da plataforma.                                                                                            |
| `base_tax`            | Taxa da plataforma (`base_fixed_tax` mais `base_percentage_tax`).                                                                                  |
| `installment_tax`     | Juros do parcelamento.                                                                                                                             |
| `base_fixed_tax`      | Parte fixa da taxa da plataforma.                                                                                                                  |
| `base_percentage_tax` | Parte percentual da taxa, já em reais.                                                                                                             |
| `installments`        | Número de parcelas. `1` à vista.                                                                                                                   |
| `cycle`               | Ciclo da assinatura. `1` na primeira cobrança e em vendas avulsas.                                                                                 |
| `paid_at`             | Data e hora do pagamento. `null` enquanto não pago.                                                                                                |
| `created_at`          | Data e hora da criação.                                                                                                                            |

Campos extras em alguns eventos:

| Evento                                               | Campos a mais em `transaction`                                                                    |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `TRANSACTION_ASK_REFUNDING` e `TRANSACTION_REFUNDED` | `refund_reason` (motivo do pedido) e `refund_at` (data do estorno, `null` enquanto só foi pedido) |
| `TRANSACTION_CHARGEBACK_APPROVED`                    | `chargeback_approved_at` (data da aprovação do chargeback)                                        |

### `items`

| Campo             | O que é                                                                                                                                       |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | Id do item.                                                                                                                                   |
| `quantity`        | Quantidade.                                                                                                                                   |
| `amount`          | Valor cobrado pelo item, já com desconto.                                                                                                     |
| `original_amount` | Valor antes do desconto.                                                                                                                      |
| `discount_value`  | Desconto aplicado.                                                                                                                            |
| `product`         | Produto do item: `id`, `name` e `type`. Pode vir `null`.                                                                                      |
| `price`           | Oferta do item: `id`, `title`, `price` e `identifier` (código da oferta: `PPP` seguido de 10 dígitos, como `PPP1234567890`). Pode vir `null`. |

> **Os códigos chegam com prefixo, iguais aos da API**
>
> `transaction.identifier` chega com `PPO` e `items[].price.identifier` com `PPP`, iguais aos das respostas da API e do painel. Isso vale também dentro de `order_bumps` e `reference_transaction`.

### `payment_details`

| Campo                     | O que é                                                                                                                 |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `origin`                  | Papel desta venda na compra: `DIRECT` é a venda principal; `ORDERBUMP` e `UPSELL` são ofertas adicionais ligadas a ela. |
| `qr_code`                 | Código PIX "copia e cola". `null` fora do PIX.                                                                          |
| `billet_barcode`          | Código do boleto como o gateway devolveu. `null` fora do boleto.                                                        |
| `billet_link`             | Link do PDF do boleto. `null` fora do boleto.                                                                           |
| `last_credit_card_digits` | Últimos dígitos do cartão. `null` fora do cartão.                                                                       |
| `shipping_value`          | Valor do frete. Pode vir `null`.                                                                                        |

### `subscription` dentro de um evento de venda

| Campo             | O que é               |
| ----------------- | --------------------- |
| `id`              | Id da assinatura.     |
| `status`          | Status da assinatura. |
| `start_at`        | Início da assinatura. |
| `next_billing_at` | Próxima cobrança.     |

### `coupon`

| Campo                | O que é                                                                 |
| -------------------- | ----------------------------------------------------------------------- |
| `id`, `code`, `name` | Id, código e nome do cupom.                                             |
| `fixed_value`        | Desconto fixo em reais, como número. `null` se o cupom é percentual.    |
| `percentage_value`   | Desconto percentual, como número. `10` = 10%. `null` se o cupom é fixo. |

### `affiliate`

| Campo              | O que é                                                                                                                                                |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `identifier`       | Código do afiliado: `PAO` seguido de 10 dígitos.                                                                                                       |
| `name`             | Nome da conta do afiliado: o nome fantasia ou, sem ele, a razão social.                                                                                |
| `commission_type`  | `COMMISSION` para comissão em dinheiro; `PRODUCT` para comissão em unidades do produto.                                                                |
| `commission_value` | Comissão da venda em reais, como número. `null` na comissão em produto e enquanto o repasse ao afiliado ainda não foi gerado, como antes do pagamento. |
| `product_quantity` | Unidades do produto por recompensa, na comissão em produto. `null` na comissão em dinheiro.                                                            |

Order bumps e upsells trazem o afiliado da venda principal.

## Order bumps e upsells

Uma compra no checkout pode ter itens extras (order bumps e upsells). Cada um vira uma venda separada, ligada à venda principal.

| Bloco                   | Quando aparece                                                  | O que traz                                                                      |
| ----------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `order_bumps`           | O evento é da venda principal e ela tem order bumps ou upsells. | Uma lista. Cada item tem `transaction`, `items` e `product` de uma venda extra. |
| `reference_transaction` | O evento é de um order bump ou upsell.                          | `transaction`, `items` e `product` da venda principal.                          |

Quando não se aplicam, os dois blocos **não aparecem** no JSON.

## Blocos dos eventos de assinatura

Os eventos que começam com `SUBSCRIPTION_` trazem:

| Bloco          | O que traz                                  |
| -------------- | ------------------------------------------- |
| `subscription` | A assinatura.                               |
| `product`      | O plano. Pode vir `null`.                   |
| `buyer`        | O cliente. Pode vir `null`.                 |
| `source`       | O canal da primeira cobrança da assinatura. |

### `subscription`

| Campo             | O que é                                                                                                                                                                                      |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | Id da assinatura. Use em `GET /subscriptions/{id}`.                                                                                                                                          |
| `external_id`     | Id da assinatura no gateway. `null` em PIX ou boleto e antes da confirmação no cartão.                                                                                                       |
| `status`          | Status da assinatura [no momento do envio](#estado-no-envio). Veja [Ciclo de vida da assinatura](/docs/guias/conceitos/ciclo-de-vida-da-assinatura).                                         |
| `start_at`        | Início da assinatura.                                                                                                                                                                        |
| `end_at`          | Fim da assinatura. Preenchido no cancelamento. No `SUBSCRIPTION_CANCELED` de cartão, pode chegar `null`, porque a data é gravada logo depois do envio. Confira em `GET /subscriptions/{id}`. |
| `next_billing_at` | Próxima cobrança.                                                                                                                                                                            |
| `payment_method`  | Meio de pagamento da assinatura.                                                                                                                                                             |
| `total_amount`    | Valor de cada ciclo.                                                                                                                                                                         |
| `created_at`      | Data e hora da criação.                                                                                                                                                                      |

## Canal da venda: `source`

> **Não é só o que a sua integração criou**
>
> O webhook da credencial recebe os eventos de **todas** as vendas e assinaturas da conta: as criadas pela API, as do checkout da PagPolar e as vendas manuais. Se o seu sistema só deve tratar o que ele mesmo criou, filtre pelo campo `source`.

| `source.channel` | De onde veio a venda                                                       |
| ---------------- | -------------------------------------------------------------------------- |
| `API`            | Criada pela API.                                                           |
| `CHECKOUT`       | Checkout da PagPolar.                                                      |
| `MANUAL`         | Venda cortesia gerada pelo vendedor, como um ingresso emitido manualmente. |
| `AWARD`          | Prêmio de afiliado.                                                        |

`source.api_credential_id` é o id da credencial que criou a venda, quando `channel` é `API`. Nos outros canais, chega `null`.

Regras:

* Order bumps, upsells e renovações herdam o canal da venda original.
* Nos eventos de assinatura, `source` é o canal da primeira cobrança da assinatura.

Exemplo de filtro em Node.js:

```js
const isFromMyIntegration = (payload) =>
  payload.data?.source?.channel === 'API' &&
  payload.data.source.api_credential_id === process.env.PAGPOLAR_CREDENTIAL_ID;
```

O `PAGPOLAR_CREDENTIAL_ID` é o `credential_id` que [`GET /me`](/docs/referencia/autenticacao/get-current-credential) devolve.

## O payload traz o estado do momento do envio

O `data` é montado na hora de cada tentativa, não na hora em que o evento aconteceu. Por isso:

* um `TRANSACTION_CREATED` pode chegar com `status: PAID`, se a venda foi paga antes da entrega;
* uma nova tentativa ou um reenvio pode trazer um status diferente do primeiro envio;
* um evento atrasado pode trazer um status mais antigo do que o que você já gravou, ou mais novo do que o nome do evento sugere.

Para decidir, olhe o `status` que chegou. Como tratar status atrasado está em [Não deixe o status voltar para trás](/docs/webhooks/processar-sem-duplicar#status-para-tras).

Se a venda ou a assinatura não for encontrada no momento do envio, `data` chega vazio: `{}`.

## Valores em dinheiro

Todos os valores estão em **reais**. Mas o tipo muda conforme o campo:

| Chega como **texto**                                                                                                  | Chega como **número**                           |
| --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `transaction.total_amount`, `effective_value`, `base_tax`, `installment_tax`, `base_fixed_tax`, `base_percentage_tax` | `transaction.net_amount`                        |
| `items[].amount`, `original_amount`, `discount_value`, `price.price`                                                  | `coupon.fixed_value`, `coupon.percentage_value` |
| `payment_details.shipping_value`                                                                                      |                                                 |
| `subscription.total_amount` nos eventos de assinatura                                                                 |                                                 |

Os textos têm casas decimais fixas, como `"97.0000"`. Converta para número antes de fazer contas:

```js
const totalAmount = Number(payload.data.transaction.total_amount);
```

> **Na API REST é diferente**
>
> Nas respostas da API, os valores chegam como número. Veja [Valores nas respostas](/docs/guias/fundamentos/valores-datas-e-identificadores#valores-nas-respostas).

## Datas

Datas chegam como texto em ISO 8601, como `2026-09-15T14:35:00.000Z`. Datas vazias chegam `null`.

## Dados pessoais

Diferente das [respostas da API](/docs/guias/fundamentos/valores-datas-e-identificadores#dados-pessoais-mascarados), o webhook envia `buyer.document` e `buyer.phone` **sem máscara**. Não grave o corpo completo dos avisos em logs abertos e restrinja o acesso aos dados guardados.
