API de Integração

Webhooks

Receba em tempo real os eventos das suas vendas no PrincipiaPay, com a lista de eventos, o payload e as regras de reenvio.

Webhooks notificam o seu sistema, em tempo real, sobre o que acontece com cada venda: carrinho abandonado, pagamento gerado, compra confirmada, cancelamento e outros. Com eles você automatiza réguas de recuperação, liberação de acesso e atualização do seu cadastro.

Configurar

Você pode configurar pelo painel ou pela API. Dá para ter mais de uma configuração, cada uma com a sua URL e os seus eventos.

Pelo painel

Entre no painel do parceiro com perfil Admin ou Superadmin e abra Configurações > Integrações > Webhooks.

Clique em Criar webhook e preencha: nome da configuração, URL para envio, token de autorização (opcional) e os eventos desejados.

Salve. Na tela de confirmação, use Teste de configuração > Enviar teste para disparar um envio de cada evento selecionado, com dados fictícios.

Na lista de configurações você busca pelo nome, ativa ou inativa, edita ou exclui cada uma.

Pela API

POST /webhooks
{
  "webhookUrl": "https://suaempresa.com.br/suaurlretorno",
  "enabledEvents": [
    { "name": "purchaseConfirmed" },
    { "name": "purchaseCancelled" },
    { "name": "invoiceCreated" }
  ],
  "configurationName": "Webhook - Integração",
  "authorizationToken": "seu_token_secreto"
}

configurationName, webhookUrl e enabledEvents são obrigatórios; authorizationToken é opcional. Para receber todos os eventos, envie "enabledEvents": [{ "name": "all" }].

Não cadastre a mesma URL duas vezes

Cada POST /webhooks cria uma configuração nova, mesmo que a URL já esteja cadastrada. Com duas configurações ativas para a mesma URL e o mesmo evento, você recebe esse evento duas vezes. Antes de criar, consulte GET /webhooks; para mudar eventos, token ou reativar, use PATCH /webhooks/{id}.

O teste (POST /webhooks/test/{id}) só funciona com uma configuração ativa e com eventos habilitados.

Como os eventos chegam

Todo evento é enviado com POST e corpo JSON, com estes headers:

Content-Type: application/json
authorization: seu_token_secreto

O header authorization leva o authorizationToken da configuração, exatamente como você cadastrou, e só é enviado quando a configuração tem um token. Não há assinatura (HMAC) do corpo: cadastre um token longo e aleatório e valide esse valor no seu endpoint para garantir que o envio veio do PrincipiaPay.

Eventos

EventoNome no payloadQuando é enviado
Carrinho abandonadocartAbandonmentO comprador parou no checkout sem finalizar a compra.
Aguardando pagamentoinvoiceCreatedFoi gerado um Pix, um boleto à vista ou a fatura de entrada do financiamento.
Pagamento expiradoinvoiceExpiredO Pix ou o boleto à vista venceu sem pagamento.
Pagamento recusadopaymentDeclinedUma tentativa de pagamento no cartão de crédito foi recusada.
Financiamento negadofinancingDeniedO financiamento (boleto parcelado) foi negado por crédito ou risco de fraude.
Avalista necessárioguarantorNeededO avalista precisa fazer o aceite e assinar o contrato.
Compra confirmadapurchaseConfirmedA compra foi efetivada: houve um pagamento reconhecido.
Compra canceladapurchaseCancelledA compra foi cancelada depois de confirmada, inclusive por estorno ou contestação (chargeback) do cartão.

Só pagamentos do checkout

invoiceCreated, invoiceExpired e paymentDeclined valem só para pagamentos do checkout (boleto e Pix à vista, ou a entrada do financiamento). As parcelas do financiamento não geram esses eventos.

Detalhes de cada evento

Carrinho abandonado (cartAbandonment). Chega depois que o comprador fica pelo menos 30 minutos sem interagir com o checkout, e só se ele tiver preenchido telefone ou e-mail. É enviado no máximo uma vez por venda, só para vendas com atividade nos últimos 90 minutos, e só enquanto o comprador segue pelo boleto parcelado (financiamento) ou ainda não escolheu a forma de pagamento. Não é enviado quando o comprador:

  • gerou um boleto, um Pix ou a fatura de entrada do financiamento;
  • tentou pagar no cartão sem sucesso;
  • indicou um avalista que ainda não começou o aceite;
  • teve o financiamento negado;
  • ou o avalista depende de análise manual de crédito ou risco.

Aguardando pagamento (invoiceCreated). Enviado quando o comprador gera o QR Code do Pix, gera o boleto à vista, ou é aprovado no boleto parcelado e chega à etapa de pagamento da entrada.

Pagamento expirado (invoiceExpired). O Pix ou o boleto à vista não foi pago até o vencimento. O comprador pode gerar um novo pagamento ou escolher outra forma.

Pagamento recusado (paymentDeclined). O pagamento no cartão não foi aprovado. É enviado a cada tentativa recusada; o comprador pode tentar de novo ou escolher outra forma.

Financiamento negado (financingDenied). O boleto parcelado foi negado por risco de crédito ou de fraude. Se houver outra forma disponível, o comprador pode escolhê-la.

Avalista necessário (guarantorNeeded). No boleto parcelado com avalista exigido, o comprador indicou o avalista e o CPF foi aprovado para o crédito. Enquanto o avalista não começar o fluxo dele, não há evento de carrinho abandonado.

Compra confirmada (purchaseConfirmed). O comprador pagou o boleto à vista, o Pix, o cartão de crédito ou a entrada do financiamento.

Compra cancelada (purchaseCancelled). O comprador ou o parceiro pediu o cancelamento e o pedido foi processado, ou um pagamento no cartão foi estornado ou contestado pelo comprador junto ao banco (chargeback).

financingDenied, guarantorNeeded, purchaseConfirmed e purchaseCancelled são gerados no máximo uma vez por venda. Os demais podem se repetir (por exemplo, paymentDeclined a cada tentativa recusada).

Payload

Propriedades

PropriedadeTipoDescrição
eventtextoNome do evento (ex.: cartAbandonment).
buyerobjetoDados do comprador.
buyer.nametextoNome.
buyer.emailtextoE-mail.
buyer.phonetextoTelefone com DDD, sem DDI.
buyer.personalDocumenttextoNúmero do documento.
buyer.personalDocumentTypetextoTipo do documento (hoje, só CPF).
buyer.addressobjetoEndereço: city, state (UF), number, street, zipCode, district, complement.
checkoutobjetoDados da venda.
checkout.pricetextoValor total da venda.
checkout.checkoutUrltextoURL para o comprador concluir a compra.
checkout.saleIdnúmeroID da venda no PrincipiaPay.
checkout.sellertextoE-mail do vendedor vinculado à venda.
checkout.createdAtdata e horaCriação da venda, no horário de Brasília (veja Datas).
checkout.updatedAtdata e horaÚltima atualização, no horário de Brasília.
checkout.canceledAtdata e horaCancelamento, no horário de Brasília.
checkout.madeEffectiveAtdata e horaEfetivação, no horário de Brasília.
checkout.paymentMethodslistaFormas de pagamento oferecidas: bankSlip (boleto à vista), pix (Pix à vista), creditCard (cartão), creditAsAService (crédito educacional dinâmico), antecipatedFinancing (crédito educacional antecipado).
checkout.productslistaProdutos da venda: productId, productSku, productName, variantId, variantSku, variantName, variantPrice. No painel, produto é Curso e variação é Turma. Hoje a lista traz um item, mesmo em vendas com mais de um produto: para saber tudo o que foi vendido, use o saleId para chegar à venda no seu sistema.
checkout.financingDetailsobjetoSó no boleto parcelado (financiamento).
checkout.financingDetails.currentSteptexto ou nullEtapa atual. Veja os valores em Etapas do financiamento.
checkout.financingDetails.deniedReasontexto ou nullMotivo da negativa do financiamento.
paymentobjetoDados do pagamento.
payment.paymentMethodtextoForma de pagamento escolhida.
payment.urltextoURL para pagar.
payment.dueDatetextoVencimento.
payment.digitableLinetextoLinha digitável do boleto.
payment.pix.pixQrCodetextoURL do QR Code do Pix.
payment.pix.pixQrCodeTexttextoPix "copia e cola".
payment.creditCard.cardBrandtextoBandeira do cartão, quando disponível.
payment.creditCard.lastFourDigitstextoÚltimos 4 dígitos, quando disponível.
payment.creditCard.numberOfInstallmentsnúmeroNúmero de parcelas.
payment.declinedReasontextoMotivo da recusa no cartão.
payment.financing.IOFtextoIOF do contrato.
payment.financing.pmttextoValor base da parcela.
payment.financing.takenAmounttextoValor total financiado (sem a entrada, com o IOF diluído nas parcelas).
payment.financing.upfrontAmounttextoValor da entrada, com a taxa de cadastro.
payment.financing.monthlyInteresttextoJuros mensal, em percentual.
payment.financing.userRegistrationFeetextoTaxa de cadastro.
payment.financing.numberOfInstallmentsnúmeroNúmero de parcelas do financiamento.
guarantorobjetoDados do avalista: name, email, phone, personalDocument, personalDocumentType e address (mesmos campos do comprador).

Quando cada objeto vem

ObjetoEm quais eventos
paymentAguardando pagamento, Pagamento expirado, Pagamento recusado, Compra confirmada e Compra cancelada. Pode vir null quando não há pagamento associado. Não vem em Carrinho abandonado, Financiamento negado nem Avalista necessário.
payment.financingCompra confirmada e Compra cancelada, quando a venda é pelo boleto parcelado (financiamento).
guarantorA chave vem em todos os eventos, menos em Pagamento recusado. Fica null quando não há avalista.
checkout.financingDetailsTodos os eventos de vendas pelo boleto parcelado (financiamento). currentStep e deniedReason podem vir null.

Etapas do financiamento

Valores possíveis de checkout.financingDetails.currentStep. Compare sem diferenciar maiúsculas de minúsculas, porque a mesma etapa pode chegar com grafias diferentes:

ValorEtapa
Informações básicas do alunoDados pessoais do aluno.
Indicação do avalistaO aluno precisa indicar um avalista.
Documentos do alunoDocumentos do aluno.
Documentos do avalista ou Documentos do AvalistaDocumentos do avalista.
Assinatura do contratoAssinatura do contrato.
Pagamento da entradaPagamento da entrada.
nullSem etapa definida para o evento (por exemplo, em cancelamentos).

Trate valores fora desta lista sem quebrar.

Datas

As datas de checkout (createdAt, updatedAt, canceledAt, madeEffectiveAt) vêm no formato ISO 8601 com o sufixo Z, mas o valor está no horário de Brasília (UTC-3), não em UTC. Por exemplo, "2025-01-01T21:53:04.230Z" significa 21:53 em Brasília (00:53 UTC do dia seguinte). Para converter para UTC, some 3 horas; não converta como se fosse UTC.

Exemplo

purchaseConfirmed
{
  "event": "purchaseConfirmed",
  "buyer": {
    "name": "JOHN DOE",
    "email": "johndoe@gmail.com",
    "phone": "11999999999",
    "address": {
      "city": "São Paulo",
      "state": "SP",
      "number": "1855",
      "street": "Av. Dr. Cardoso de Melo",
      "zipCode": "04548005",
      "district": "Vila Olimpia",
      "complement": "11º andar"
    },
    "personalDocument": "12345678900",
    "personalDocumentType": "CPF"
  },
  "checkout": {
    "price": "1999.00",
    "seller": null,
    "products": [
      {
        "productId": 1234,
        "productSku": "01946620-fba3-74c7-8473-38337b3f08b1",
        "productName": "Light Saber 101",
        "variantId": 3456,
        "variantSku": "01946621-1706-7cc4-8e7e-67dbd3d9ab6e",
        "variantName": "Light Saber 101 - Lançamento 1",
        "variantPrice": "1999.00"
      }
    ],
    "createdAt": "2025-01-01T21:53:04.230Z",
    "updatedAt": "2025-01-01T21:56:43.045Z",
    "canceledAt": null,
    "saleId": 1582131,
    "checkoutUrl": "https://pay.principia.net/checkout/parceiro",
    "paymentMethods": ["bankSlip", "creditCard", "pix", "creditAsAService", "antecipatedFinancing"],
    "madeEffectiveAt": null,
    "financingDetails": { "currentStep": "Pagamento da entrada", "deniedReason": null }
  },
  "guarantor": null,
  "payment": {
    "pix": {
      "pixQrCode": "https://pay.principia.net/fatura/52026bce-9f97-4c39-83f9-6bffea600303-08cc/qr_code",
      "pixQrCodeText": "00020126360014BR.GOV.BCB.PIX0114999999999999995204000053039865407199900"
    },
    "url": "https://pay.principia.net/fatura/52026bce-9f97-4c39-83f9-6bffea600303-08cc",
    "dueDate": "2025-01-05",
    "digitableLine": "00000000000000000000000000000000000000000000000",
    "paymentMethod": "antecipatedFinancing",
    "financing": {
      "IOF": "35.36",
      "pmt": "194.77",
      "takenAmount": "1834.45",
      "upfrontAmount": "219.89",
      "monthlyInterest": "3.99",
      "userRegistrationFee": "19.99",
      "numberOfInstallments": 12
    }
  }
}

Reenvio

O primeiro envio sai cerca de 15 segundos depois do evento. Um envio conta como sucesso quando a sua URL responde com um status 2XX (ex.: 200 OK). São 4 tentativas no total: o envio original e mais 3 reenvios.

TentativaQuando
1ª (original)Cerca de 15 segundos depois do evento
2ª2 minutos depois da falha da 1ª
3ª5 minutos depois da falha da 2ª
4ª15 minutos depois da falha da 3ª

Depois da quarta tentativa sem sucesso, o evento não é mais enviado. O histórico de envios é guardado, mas ainda não dá para consultá-lo pelo painel nem pela API.

Boas práticas

  • Valide o header authorization em todo envio.
  • Responda 2XX rápido e processe o evento depois (em fila, por exemplo), para não estourar o tempo e cair no reenvio.
  • Processe os eventos de forma idempotente: por causa do reenvio (ou de duas configurações com a mesma URL), o mesmo evento pode chegar mais de uma vez, e receber o mesmo purchaseConfirmed duas vezes não pode, por exemplo, liberar o acesso duas vezes. Lembre que paymentDeclined chega uma vez por tentativa recusada.
  • Trate as datas como horário de Brasília (veja Datas).
  • Guarde os eventos recebidos no seu lado, para auditoria.

Webhooks legado

Se a sua conta também tem configurações do sistema antigo (rotas /webhook/..., versões 1.0 e 2.0) ou vendas criadas com notification_url, esses envios continuam acontecendo em paralelo aos webhooks descritos nesta página. Com os dois sistemas configurados, você recebe os dois formatos para a mesma venda. Ao migrar, inative as configurações antigas.

Nesta página