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. |
X-PagPolar-Test | true, só nos envios de teste do 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. |
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 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
{
"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:
| 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. |
source | O canal em que a venda nasceu. |
order_bumps | Só aparece em alguns casos. Veja Order bumps e upsells. |
reference_transaction | Só aparece em alguns casos. Veja 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. Veja 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. Veja 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:
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_CREATEDpode chegar comstatus: 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 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:
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.