Uma checkout session é uma tentativa única de compra: uma sessão descartável
que coleta o comprador, apresenta os métodos de pagamento e confirma a cobrança.
Este guia percorre cada decisão que você toma no POST /v1/checkout-sessions e o
que a Chargefy resolve do lado dela. O schema completo está em
Criar checkout session.
O que você sempre envia: line_items
line_items é o único campo obrigatório. Cada item assume exatamente uma de
três formas.
(a) Preço do catálogo
O caminho mais curto: um preço que você já cadastrou. Produto, valor e
recorrência saem do próprio preço.
curl -X POST https://api.chargefy.io/v1/checkout-sessions \
-H "Authorization: Bearer {{API_KEY}}" \
-H "Content-Type: application/json" \
-d '{
"line_items": [{ "price_id": "price_789", "quantity": 1 }]
}'
(b) Produto do catálogo + valor ad-hoc
Reusa o produto cadastrado (nome/descrição), mas com um valor único desta sessão.
Não cria um preço novo no catálogo.
curl -X POST https://api.chargefy.io/v1/checkout-sessions \
-H "Authorization: Bearer {{API_KEY}}" \
-H "Content-Type: application/json" \
-d '{
"line_items": [{
"price_data": {
"currency": "brl",
"product_id": "prod_123",
"unit_amount": 14990
},
"quantity": 1
}]
}'
(c) Tudo ad-hoc (headless)
Sem catálogo: produto e valor existem só nesta sessão.
curl -X POST https://api.chargefy.io/v1/checkout-sessions \
-H "Authorization: Bearer {{API_KEY}}" \
-H "Content-Type: application/json" \
-d '{
"line_items": [{
"price_data": {
"currency": "brl",
"product_data": { "name": "Consultoria avulsa" },
"unit_amount": 50000
},
"quantity": 1
}]
}'
Regras do array, validadas no create (cada uma retorna 400):
- Todos os itens compartilham a mesma
currency.
- Ou todos os itens são recorrentes, ou nenhum é — sem misturar.
- Cada item tem exatamente um entre
price_id e price_data.
- Com
price_data, exatamente um entre product_id e product_data.
Pagamento único ou assinatura
Você não envia mode — ele é derivado dos line_items. Se algum item é
recorrente (preço com recorrência, ou price_data.recurring), a sessão vira
mode: "subscription"; senão, mode: "payment".
Para assinaturas, subscription_data controla o trial. Use um de
trial_period_days ou trial_end:
curl -X POST https://api.chargefy.io/v1/checkout-sessions \
-H "Authorization: Bearer {{API_KEY}}" \
-H "Content-Type: application/json" \
-d '{
"line_items": [{
"price_data": {
"currency": "brl",
"product_data": { "name": "Plano Pro" },
"recurring": { "interval": "month" },
"unit_amount": 4990
}
}],
"subscription_data": {
"trial_period_days": 7,
"trial_settings": {
"end_behavior": { "missing_payment_method": "pause" }
}
}
}'
Quando há trial, o comprador informa o cartão mas nenhuma cobrança acontece no
checkout: a sessão fecha com payment_status: "no_payment_required" e a
assinatura nasce em período de teste. A primeira cobrança real ocorre ao fim do
trial. Não criar assinatura sem um preço recorrente — não existe assinatura sem
price_id/price_data recorrente.subscription_data.trial_settings.end_behavior.missing_payment_method controla
o fim do trial quando não há payment method salvo: create_invoice abre uma
invoice, pause deixa a assinatura em paused sem gerar invoice, e cancel
cancela a assinatura.
Vincular a um cliente
Como a sessão se relaciona ao customer depende do que você envia:
| O que você envia | Comportamento |
|---|
customer (id de cliente existente) | A sessão fica travada nesse cliente. O e-mail vem preenchido e somente leitura; o id do cliente não muda. |
customer_email / customer_document (sem customer) | Pré-preenchem os campos. Nenhum cliente é criado no create. |
| Nada | Checkout de convidado: campos editáveis. |
# Travado a um cliente que já existe no seu sistema
curl -X POST https://api.chargefy.io/v1/checkout-sessions \
-H "Authorization: Bearer {{API_KEY}}" \
-H "Content-Type: application/json" \
-d '{
"customer": "cus_123",
"line_items": [{ "price_id": "price_789", "quantity": 1 }]
}'
O cliente é resolvido uma única vez no confirm, com os dados finais. Sem
customer, a Chargefy cria um cliente novo — o e-mail não é usado para
reaproveitar um cliente existente, porque e-mail não é chave de identidade
(vários clientes podem ter o mesmo e-mail na organização). Se você quer reusar um
cliente, faça o lookup na sua base e passe o customer. Veja
Gestão de clientes.
O documento (CPF/CNPJ) é a chave soberana da identidade de pagamento:
instrumentos salvos (cartões) são organizados por ele. Documentos diferentes
geram identidades de pagamento diferentes — o que evita atrelar um cartão à
pessoa errada.
Campos obrigatórios do comprador
Por padrão a sessão herda a política da organização, mas você pode sobrescrever
por sessão:
| Campo | Efeito |
|---|
require_document | Exige CPF/CNPJ em qualquer método. |
require_phone | Exige telefone (enviado no confirm como customer_details.phone). |
require_billing_address | Exige endereço de cobrança. |
Esses flags só adicionam exigências sobre o piso de cada método — boleto, por
exemplo, sempre exige documento e endereço, independentemente da política.
Aparência
Três eixos independentes, todos opcionais:
| Campo | Controla |
|---|
template | Estrutura/layout da página: minimal ou booking. |
branding_settings | Cor, fonte, tema (claro/escuro) e estilo de borda. null herda 100% da organização. |
submit_type | Verbo do botão: auto, pay, subscribe, book, donate. |
curl -X POST https://api.chargefy.io/v1/checkout-sessions \
-H "Authorization: Bearer {{API_KEY}}" \
-H "Content-Type: application/json" \
-d '{
"branding_settings": { "brand_color": "#5149EF", "theme": "light" },
"line_items": [{ "price_id": "price_789", "quantity": 1 }],
"submit_type": "pay"
}'
Descontos
Há duas formas, que coexistem:
- Desconto automático — passe
discount_id no create; ele já entra aplicado.
- Cupom do comprador — deixe
allow_discount_codes ativo (padrão) e o
comprador digita o código na própria página.
curl -X POST https://api.chargefy.io/v1/checkout-sessions \
-H "Authorization: Bearer {{API_KEY}}" \
-H "Content-Type: application/json" \
-d '{
"discount_id": "di_123",
"line_items": [{ "price_id": "price_789", "quantity": 1 }]
}'
Métodos de pagamento
Por padrão a sessão oferece todos os métodos habilitados na organização. Os
métodos disponíveis chegam no campo payment_method_types da resposta, e a
página só mostra as abas correspondentes.
Entregar ao comprador
A resposta traz dois caminhos — escolha um:
url — a página hospedada, pronta. Redirecione o comprador.
client_secret — credencial de runtime do browser (não é segredo de
servidor) para um frontend próprio chamar as rotas públicas de consulta e
confirmação sem expor a sua API key.
A confirmação acontece no browser via
POST /v1/checkout-sessions/public/:client_secret/confirm. O seu servidor não
precisa criar nem confirmar nenhuma movimentação interna — veja
Confirmar checkout session.
Ciclo de webhooks
| Evento | Quando |
|---|
checkout.session.created | A sessão foi criada. |
checkout.session.completed | O comprador concluiu o checkout. Em cartão, normalmente já pago; em PIX/boleto, ainda aguarda compensação. |
checkout.session.async.payment.succeeded | PIX/boleto compensou — evento confiável para liberar produto em pagamento assíncrono. |
checkout.session.async.payment.failed | O pagamento assíncrono falhou ou expirou. |
checkout.session.expired | A sessão passou das 24h sem confirmação. |
O metadata que você enviou é ecoado em todos esses eventos, então você
reconcilia o resultado contra o seu pedido guardando apenas o seu próprio
identificador.