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:

HeaderValor
Content-Typeapplication/json
AuthorizationBearer seguido do token do webhook. Veja Autenticar as requisições recebidas.
X-PagPolar-Testtrue, só nos envios de teste do Playground. Os eventos reais não trazem este header.

Envelope

Todo evento tem o mesmo envelope:

CampoTipoO que é
idtexto (uuid)Id desta tentativa de entrega. Não serve para descartar repetidos.
eventtextoNome do evento, como TRANSACTION_PAID.
creation_datetexto (data e hora)Quando esta tentativa foi montada, em UTC.
versiontextoVersão do formato. Hoje é 1.0.0.
testbooleanoSó aparece, com true, nos envios de teste do Playground Os eventos reais não trazem o campo. Em produção, ignore qualquer evento com test: true.
dataobjetoOs dados do evento.

Exemplo de evento de venda

{
  "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.

Blocos dos eventos de venda

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

BlocoO que traz
transactionA venda.
itemsOs itens da venda, com produto e oferta.
productO produto principal da venda. Pode vir null.
buyerO cliente. Pode vir null.
addressO endereço informado na compra. Pode vir null.
payment_detailsDados do pagamento: QR Code, boleto e final do cartão. Pode vir null.
couponO cupom usado. null sem cupom.
subscriptionResumo da assinatura, quando a venda é de uma assinatura. Senão, null.
affiliateO afiliado que indicou a venda. null sem afiliado. Veja affiliate.
sourceO canal em que a venda nasceu.
order_bumpsSó aparece em alguns casos. Veja Order bumps e upsells.
reference_transactionSó aparece em alguns casos. Veja Order bumps e upsells.

transaction

CampoO que é
idId da venda. Use para ligar ao seu pedido e para consultar GET /sales/{identifier}.
identifierCó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.
statusStatus da venda no momento do envio. Veja Ciclo de vida da venda.
typeTipo da venda. BILLING é a cobrança ao cliente.
payment_methodMeio de pagamento, como PIX, BOLETO ou CREDIT_CARD.
total_amountValor pago pelo cliente, com juros do parcelamento.
net_amountValor da venda sem juros do parcelamento (total_amount menos installment_tax). É o valor indicado para conciliação.
effective_valueValor que fica para você, depois da taxa da plataforma.
base_taxTaxa da plataforma (base_fixed_tax mais base_percentage_tax).
installment_taxJuros do parcelamento.
base_fixed_taxParte fixa da taxa da plataforma.
base_percentage_taxParte percentual da taxa, já em reais.
installmentsNúmero de parcelas. 1 à vista.
cycleCiclo da assinatura. 1 na primeira cobrança e em vendas avulsas.
paid_atData e hora do pagamento. null enquanto não pago.
created_atData e hora da criação.

Campos extras em alguns eventos:

EventoCampos a mais em transaction
TRANSACTION_ASK_REFUNDING e TRANSACTION_REFUNDEDrefund_reason (motivo do pedido) e refund_at (data do estorno, null enquanto só foi pedido)
TRANSACTION_CHARGEBACK_APPROVEDchargeback_approved_at (data da aprovação do chargeback)

items

CampoO que é
idId do item.
quantityQuantidade.
amountValor cobrado pelo item, já com desconto.
original_amountValor antes do desconto.
discount_valueDesconto aplicado.
productProduto do item: id, name e type. Pode vir null.
priceOferta 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

CampoO que é
originPapel desta venda na compra: DIRECT é a venda principal; ORDERBUMP e UPSELL são ofertas adicionais ligadas a ela.
qr_codeCódigo PIX "copia e cola". null fora do PIX.
billet_barcodeCódigo do boleto como o gateway devolveu. null fora do boleto.
billet_linkLink do PDF do boleto. null fora do boleto.
last_credit_card_digitsÚltimos dígitos do cartão. null fora do cartão.
shipping_valueValor do frete. Pode vir null.

subscription dentro de um evento de venda

CampoO que é
idId da assinatura.
statusStatus da assinatura.
start_atInício da assinatura.
next_billing_atPróxima cobrança.

coupon

CampoO que é
id, code, nameId, código e nome do cupom.
fixed_valueDesconto fixo em reais, como número. null se o cupom é percentual.
percentage_valueDesconto percentual, como número. 10 = 10%. null se o cupom é fixo.

affiliate

CampoO que é
identifierCódigo do afiliado: PAO seguido de 10 dígitos.
nameNome da conta do afiliado: o nome fantasia ou, sem ele, a razão social.
commission_typeCOMMISSION para comissão em dinheiro; PRODUCT para comissão em unidades do produto.
commission_valueComissã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_quantityUnidades 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.

BlocoQuando apareceO que traz
order_bumpsO 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_transactionO 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:

BlocoO que traz
subscriptionA assinatura.
productO plano. Pode vir null.
buyerO cliente. Pode vir null.
sourceO canal da primeira cobrança da assinatura.

subscription

CampoO que é
idId da assinatura. Use em GET /subscriptions/{id}.
external_idId da assinatura no gateway. null em PIX ou boleto e antes da confirmação no cartão.
statusStatus da assinatura no momento do envio. Veja Ciclo de vida da assinatura.
start_atInício da assinatura.
end_atFim 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_atPróxima cobrança.
payment_methodMeio de pagamento da assinatura.
total_amountValor de cada ciclo.
created_atData 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.channelDe onde veio a venda
APICriada pela API.
CHECKOUTCheckout da PagPolar.
MANUALVenda cortesia gerada pelo vendedor, como um ingresso emitido manualmente.
AWARDPrê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:

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 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.

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 textoChega como número
transaction.total_amount, effective_value, base_tax, installment_tax, base_fixed_tax, base_percentage_taxtransaction.net_amount
items[].amount, original_amount, discount_value, price.pricecoupon.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:

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.

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, 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.