API de Integração

Checkout

Como criar uma venda com POST /sales, mapear produtos e variações, aplicar desconto e consultar a venda.

Cada checkout é uma venda iniciada para um comprador (CPF). Você cria a venda com POST /sales e recebe um link único para o comprador concluir a compra.

Criar o checkout

curl -X POST https://app-staging.principia.services/checkout/v4/sales \
  -H "Api-Token: SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d @venda.json
venda.json
{
  "cpf": "48096807544",
  "externalSaleId": "aef2828a-e9eb-4714-b0b5-aa3edf15f31d",
  "checkoutPriceInCents": 100000,
  "products": [
    {
      "productSku": "01946620-fba3-74c7-8473-38337b3f08b1",
      "productName": "Light Saber 101",
      "variantSku": "01946621-1706-7cc4-8e7e-67dbd3d9ab6e",
      "variantName": "Light Saber 101",
      "variantPriceInCents": 100000
    }
  ],
  "buyer": {
    "name": "Darth Vader",
    "phone": "71999999999",
    "email": "darth.vader@empire.com",
    "zipCode": "04548004",
    "street": "Av. Dr. Cardoso de Melo",
    "number": "1340",
    "district": "Vila Olimpia",
    "city": "São Paulo",
    "complement": "Cj 11"
  }
}

Campos

CampoTipoObrigatórioDescrição
cpftextosimCPF do aluno para quem é a venda. Precisa ser um CPF válido.
externalSaleIdtextonãoID da venda no seu sistema, para vínculo. Recomendamos até 40 caracteres.
checkoutPriceInCentsinteirosimPreço total exibido no checkout, em centavos. Deve ser menor ou igual à soma dos produtos e ficar dentro dos limites de valor configurados para a sua conta.
upfrontInCentsinteironãoValor da entrada, em centavos. Veja Valor da entrada.
returnUrltextonãoAceito e guardado, mas não é usado hoje: o comprador não é redirecionado para essa página ao concluir o checkout. Para redirecionar, veja Embutir o checkout.
productslistasimProdutos e variações da venda (veja abaixo). Precisa ter ao menos um item.
buyerobjetosimDados do comprador. O objeto é obrigatório, mas os campos dentro dele são opcionais.

Cada item de products (todos obrigatórios):

CampoTipoDescrição
productSkutextoID do produto no seu sistema. Recomendamos até 40 caracteres.
productNametexto (8 a 99)Nome do produto. Usado só quando o produto ainda não existe. Veja as regras em Produtos e variações.
variantSkutextoID da variação no seu sistema. Recomendamos até 40 caracteres.
variantNametextoNome da variação. Recomendamos até 99 caracteres.
variantPriceInCentsinteiroPreço da variação no checkout, em centavos.

Campos de buyer:

CampoTipoDescrição
nametextoNome completo.
phonetextoTelefone com DDD, sem DDI e sem formatação. Todo telefone é tratado como +55 (Brasil).
emailtextoE-mail.
zipCodetextoCEP, só números.
streettextoLogradouro.
numbertextoNúmero.
districttextoBairro.
citytextoCidade.
complementtextoComplemento.

Tamanhos são recomendações

A API não valida o tamanho dos campos de buyer, do externalSaleId nem dos SKUs. Use os limites sugeridos acima e dados bem formados: é isso que aparece preenchido para o comprador no checkout, e ele pode corrigir o que estiver errado. A exceção é o productName, que tem regras próprias (veja abaixo).

Valor da entrada

upfrontInCents define a entrada paga pelo comprador. As regras:

  • O mínimo é o maior entre o percentual de entrada configurado para a sua conta (aplicado sobre a soma dos variantPriceInCents) e R$ 30,00.
  • A entrada precisa ser menor que a soma dos variantPriceInCents.
  • Sem o campo, o PrincipiaPay usa o mínimo.

Um valor abaixo do mínimo, ou igual ou maior que a soma dos produtos, devolve 400 (veja Erros).

Resposta

{
  "checkoutUrl": "https://pay-staging.principia.net/checkout/web-development-school?classes=44099&saleId=31397dea-d328-4135-9619-a6ed4ca7713f",
  "externalSaleId": "aef2828a-e9eb-4714-b0b5-aa3edf15f31d",
  "saleId": 1582050
}
  • checkoutUrl: redirecione o comprador para essa URL (ou embuta o checkout na sua página).
  • externalSaleId: o seu ID, se enviado.
  • saleId: ID da venda no PrincipiaPay. Guarde para consultar a venda e casar com os eventos de webhook.

Produtos e variações

Todo checkout precisa de um Produto e de uma Variação. O produto é a entidade pai e a variação é a filha. No painel do parceiro, o produto aparece como Curso e a variação como Turma.

Você não precisa cadastrar nada antes: ao criar a venda, o PrincipiaPay encontra ou cadastra produtos e variações pelos seus SKUs:

Produto (curso): é identificado só pelo productSku. Se já existir um produto com esse SKU, ele é usado; senão, é criado com o productName enviado.

Variação (turma): é identificada pelo variantSku e pelo variantPriceInCents, dentro do produto. Se já existir uma variação com esse SKU e esse preço, ela é usada; senão, é criada uma nova com o variantName enviado.

Nomes não são atualizados

Enviar outro productName ou variantName para um SKU que já existe não muda o nome cadastrado nem cria cadastro novo: o checkout continua mostrando o nome antigo. Mudar o variantPriceInCents cria uma variação nova com o preço novo; a variação antiga continua cadastrada. Para renomear, use o painel do parceiro.

A mesma venda pode ter mais de um produto, e também mais de uma variação do mesmo produto (uma entrada em products para cada variação).

Regras para cadastrar produto e variação

Quando o SKU ainda não existe, o cadastro automático aplica estas regras. Se alguma falhar, a venda não é criada:

  • Nome do produto (productName): ao menos 8 caracteres, com ao menos uma letra (a-z), e no máximo 99 caracteres (o tamanho do cadastro; um nome maior faz a venda falhar).
  • Nome único por conta: não pode existir outro produto seu com o mesmo nome, sem diferenciar maiúsculas de minúsculas. Dois productSku diferentes com o mesmo productName fazem a segunda venda falhar com Curso já existe.. Use um nome distinto para cada SKU.
  • Preço da variação (variantPriceInCents): dentro dos limites de valor configurados para a sua conta.

As regras de nome e de preço devolvem 400 com a mensagem em português, no formato { "error": { "name", "message" } }:

{
  "error": {
    "name": "BodyPropertyError",
    "message": "Curso já existe."
  }
}

No checkout, o comprador vê o nome do produto e o da variação:

Nome do produto e da variação no checkout

Seu sistema pode ter outra estrutura. A variação é o cadastro que define o preço base; considere isso ao mapear.

Produtos com ofertas. Seu sistema tem produtos (pai) e cada produto tem várias ofertas, que definem o preço. Mapeie produto para Produto e oferta para Variação. Se a oferta não tiver descrição visível ao comprador, repita o nome do produto na variação.

"products": [
  {
    "productSku": "ABC",
    "productName": "Light Saber 101",
    "variantSku": "123",
    "variantName": "Light Saber 101",
    "variantPriceInCents": 100000
  }
]

Só produtos. Seu sistema tem apenas o produto, que já define o preço. Mapeie 1 para 1: o mesmo produto vira Produto e Variação.

"products": [
  {
    "productSku": "ABC",
    "productName": "Light Saber 101",
    "variantSku": "ABC",
    "variantName": "Light Saber 101",
    "variantPriceInCents": 100000
  }
]

Dados do comprador

Envie o que tiver em buyer: os dados enviados já aparecem preenchidos no checkout. O que faltar é pedido ao comprador durante o checkout.

O CPF não muda

O comprador pode revisar e alterar os dados pessoais no checkout, mas o CPF vinculado à venda não pode ser alterado.

Embutir o checkout (iframe)

Você pode abrir a checkoutUrl dentro de um <iframe> na sua página. Dentro do iframe, o checkout esconde o rodapé e parte do cabeçalho do PrincipiaPay. Acrescente estes parâmetros à checkoutUrl para ajustar o comportamento:

ParâmetroFunciona fora do iframe?O que faz
redirectUrlnãoURL (codificada com encodeURIComponent) para onde a janela principal (a sua página, não o iframe) é levada cerca de 5 segundos depois de a compra dar certo.
supportnãoCom support=true, mostra um botão flutuante de WhatsApp do suporte do PrincipiaPay (só em telas médias e grandes).
hideBoletoAsUpfrontnãoCom hideBoletoAsUpfront=true, esconde o bloco do boleto bancário na página de pagamento da entrada (fatura).
userDatasimJSON (codificado com encodeURIComponent) com dados para pré-preencher o formulário, por exemplo CPF, fullName, email, phone e zipcode. Dados que o PrincipiaPay já tem da venda prevalecem.
https://pay.principia.net/checkout/sua-empresa?classes=44099&saleId=...&redirectUrl=https%3A%2F%2Fsuaempresa.com.br%2Fobrigado

Quando o redirecionamento acontece:

  • Cartão de crédito: depois do pagamento aprovado ou em análise.
  • Pix e boleto: não redireciona enquanto o pagamento está pendente. No Pix, o checkout confere o pagamento periodicamente e redireciona quando ele é confirmado com a página ainda aberta.
  • Página de pagamento da entrada (fatura): redireciona quando a fatura aparece como paga.

O redirecionamento não confirma a venda

O comprador pode fechar a página antes dos 5 segundos, e boleto e Pix costumam ser pagos depois. Use os eventos de webhook para saber se a venda foi paga.

Venda com desconto

Para dar desconto, informe em checkoutPriceInCents o valor já descontado. Ele precisa ser menor ou igual à soma dos variantPriceInCents e continuar dentro dos limites de valor configurados para a sua conta.

Exemplo com 20% de desconto: dois produtos, de R$ 1.000,00 e R$ 500,00 (total de R$ 1.500,00), vendidos por R$ 1.200,00.

{
  "cpf": "48096807544",
  "checkoutPriceInCents": 120000,
  "externalSaleId": "aef2828a-e9eb-4714-b0b5-aa3edf15f31d",
  "products": [
    {
      "productSku": "01946620-fba3-74c7-8473-38337b3f08b1",
      "productName": "Light Saber 101",
      "variantSku": "01946621-1706-7cc4-8e7e-67dbd3d9ab6e",
      "variantName": "Light Saber 101",
      "variantPriceInCents": 100000
    },
    {
      "productSku": "d3878e08-a625-4d11-9e09-1d8d8bce92d9",
      "productName": "Jedi Explorer",
      "variantSku": "009df0d89-3907-42b0-85db-9df7d775cd6e",
      "variantName": "Beginner Level",
      "variantPriceInCents": 50000
    }
  ],
  "buyer": { "name": "Darth Vader", "email": "darth.vader@empire.com" }
}

O checkout mostra o valor de cada produto e o percentual de desconto:

Checkout com desconto de 20%

Consultar a venda

RotaQuando usar
GET /sales/purchase/{saleId}Você tem o saleId devolvido na criação.
GET /sales/external-purchase/{externalSaleId}Você tem só o seu ID. Como o mesmo externalSaleId pode estar em mais de uma venda, a resposta é uma lista com as até 50 vendas mais recentes com esse ID. A ordem dos itens não é garantida: ordene pelo saleId ou pelo que fizer sentido no seu lado.

As duas devolvem uma lista de vendas (a consulta por saleId devolve uma lista com um item). Se nenhuma venda da sua conta for encontrada, a resposta é 400 (não 404):

{
  "name": "ValidationError",
  "errors": [{ "name": "SALE-001", "message": "Sale not found" }]
}

SKU em maiúsculo na resposta

Na resposta, os produtos vêm com productSKU e variantSKU (SKU em maiúsculo), diferente do corpo de criação (productSku e variantSku).

Com venda encontrada, o formato é este:

[
  {
    "checkoutUrl": "https://pay-staging.principia.net/checkout/web-development-school?classes=44099&saleId=31397dea-d328-4135-9619-a6ed4ca7713f",
    "externalSaleId": "aef2828a-e9eb-4714-b0b5-aa3edf15f31d",
    "status": "Efetivado",
    "saleId": 1582050,
    "cpf": "48096807544",
    "checkoutPriceInCents": 120000,
    "products": [
      {
        "productSKU": "01946620-fba3-74c7-8473-38337b3f08b1",
        "productName": "Light Saber 101",
        "variantSKU": "01946621-1706-7cc4-8e7e-67dbd3d9ab6e",
        "variantName": "Light Saber 101",
        "variantPriceInCents": 100000
      }
    ],
    "buyer": {
      "name": "Darth Vader",
      "phone": "71999999999",
      "email": "darth.vader@empire.com",
      "zipCode": "04548004",
      "street": "Av. Dr. Cardoso de Melo",
      "number": "1340",
      "district": "Vila Olimpia",
      "city": "São Paulo",
      "complement": "Cj 11"
    }
  }
]

Os valores de status estão em Status. O status pode vir null.

Nesta página