> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chargefy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Criar uma Sessão de checkout

> Crie uma Checkout Session pela API, personalize a compra, redirecione o comprador e confirme o resultado por webhook.

Crie uma Checkout Session no seu backend quando cada pedido precisar nascer com
itens, valores, comprador ou regras próprias. A resposta entrega uma `url`
temporária: redirecione o comprador e deixe a Chargefy cuidar da página, da
coleta dos dados e da confirmação do método escolhido.

Este guia cobre o fluxo hospedado. Você não precisa instalar um SDK para
começar; qualquer cliente HTTP pode chamar a API.

## O que você vai implementar

| Etapa                 | Onde acontece          | Resultado                                                                 |
| --------------------- | ---------------------- | ------------------------------------------------------------------------- |
| Criar a sessão        | Seu backend            | A API registra uma tentativa de compra e devolve `url` e `client_secret`. |
| Abrir o checkout      | Navegador do comprador | A página apresenta itens, dados necessários e formas de pagamento.        |
| Retornar ao seu site  | Navegador do comprador | `success_url` ou `cancel_url` recebe o comprador.                         |
| Confirmar o pagamento | Seu backend            | Webhooks informam quando liberar produto, acesso ou assinatura.           |

<Frame caption="A URL da sessão abre uma página hospedada pronta para cartão, Pix ou boleto.">
  <img src="https://mintcdn.com/scaleup-28315a31/AL7TxjaPFJ8w5l48/assets/accept-your-first-payment/checkout-card.png?fit=max&auto=format&n=AL7TxjaPFJ8w5l48&q=85&s=be39c5ad8c1972d9c372b40935ae1330" alt="Página de checkout hospedada pela Chargefy com resumo do pedido e formulário de pagamento" width="2560" height="1800" data-path="assets/accept-your-first-payment/checkout-card.png" />
</Frame>

## Antes de começar

Você precisa de:

1. uma organização Chargefy; para confirmar pagamentos no ambiente live, o
   cadastro financeiro precisa estar ativo;
2. uma API key do ambiente de teste, criada em **Developers → Chaves de API**;
3. uma rota no seu backend para criar a sessão;
4. um endpoint HTTPS para receber webhooks antes de liberar o pedido.

<Warning>
  A API key é uma credencial de servidor. Nunca a coloque no JavaScript enviado
  ao navegador, em uma URL ou no aplicativo do comprador.
</Warning>

## 1. Crie a sessão no backend

O menor request possível envia apenas `line_items`. Este exemplo usa um preço
já cadastrado no catálogo:

```bash theme={"theme":"css-variables"}
curl -X POST "https://api.chargefy.io/v1/checkout-sessions" \
  -H "Authorization: Bearer {{API_KEY}}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: checkout-order-8f4c2a" \
  -d '{
    "line_items": [
      {
        "price_id": "price_w9A2hszZXxVwxRaG",
        "quantity": 1
      }
    ],
    "metadata": {}
  }'
```

Use uma `Idempotency-Key` estável por pedido. Se o seu backend repetir a mesma
chamada por timeout ou retry, a Chargefy devolve o mesmo resultado em vez de
criar duas sessões para a mesma ação.

A resposta contém o objeto completo. Para o redirect, os campos mais
importantes são:

```json theme={"theme":"css-variables"}
{
  "id": "cs_3fH8kP2rV7mQ9xW4",
  "object": "checkout.session",
  "client_secret": "d144fd5098ece4425e053953313138fd0e9a04990da0bca59775cb7f2568200b",
  "expires_at": "2026-08-12T14:00:00Z",
  "livemode": false,
  "metadata": {},
  "payment_status": "unpaid",
  "status": "open",
  "url": "https://pay.chargefy.io/session/9f4c2a1b8e3d7f06a5c4b2e1d8f3a6b09c5e2a1f4b7d8c3e6a9f1d2c4b5e8a0f",
  "...": "demais campos da Checkout Session"
}
```

| Campo            | Como usar                                                                                     |
| ---------------- | --------------------------------------------------------------------------------------------- |
| `url`            | Redirecione o navegador para a página hospedada.                                              |
| `id`             | Identifique a sessão em consultas feitas pelo backend.                                        |
| `client_secret`  | Autoriza somente o runtime dessa sessão no navegador; não é necessário no redirect hospedado. |
| `expires_at`     | Depois desse horário, crie outra sessão. O prazo fixo é de 24 horas.                          |
| `status`         | A sessão nasce `open`.                                                                        |
| `payment_status` | Nasce `unpaid` ou `no_payment_required` quando nada é devido.                                 |

`mode`, totais, `expires_at`, `client_secret` e `url` são calculados pela
Chargefy. Não os envie no request.

## 2. Escolha como descrever os itens

Cada item aceita exatamente uma das três variantes abaixo. Em todas elas,
`quantity` é opcional e começa em `1`.

### a. Preço do catálogo

Use quando produto, valor e recorrência já estiverem cadastrados. É o payload
mais curto e mantém a oferta centralizada no catálogo.

```bash theme={"theme":"css-variables"}
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_w9A2hszZXxVwxRaG",
        "quantity": 1
      }
    ],
    "metadata": {}
  }'
```

### b. Produto do catálogo com preço ad-hoc

Use quando o produto já existe, mas o valor vale apenas para essa compra. A
Chargefy reutiliza o nome e a descrição do produto sem criar outro Price.

```bash theme={"theme":"css-variables"}
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_PBNzo3CF3vAZee7b",
          "unit_amount": 12990
        },
        "quantity": 1
      }
    ],
    "metadata": {}
  }'
```

### c. Produto e preço ad-hoc

Use quando o seu sistema é a fonte do catálogo. Produto e preço vivem somente
na sessão e não são persistidos como recursos reutilizáveis.

```bash theme={"theme":"css-variables"}
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": {
            "description": "Sessão individual de 60 minutos",
            "name": "Consultoria avulsa"
          },
          "unit_amount": 4990
        },
        "quantity": 1
      }
    ],
    "metadata": {}
  }'
```

### Regras de `line_items`

* envie exatamente um entre `price_id` e `price_data` em cada item;
* com `price_data`, envie exatamente um entre `product_id` e `product_data`;
* todos os itens precisam usar a mesma moeda;
* todos precisam ser avulsos ou todos recorrentes;
* `quantity` deve ser um inteiro maior ou igual a `1`;
* `unit_amount` usa centavos: `12990` representa R\$ 129,90.

| Campo do item                 | Uso                                                                                                            |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `description`                 | Sobrescreve a descrição exibida para aquele item.                                                              |
| `metadata`                    | Mantém dados livres do item no snapshot da sessão.                                                             |
| `adjustable_quantity.enabled` | Permite que o comprador altere a quantidade.                                                                   |
| `adjustable_quantity.minimum` | Define o menor valor permitido; o padrão é `0`, respeitando ao menos um item quando ele for o único da compra. |
| `adjustable_quantity.maximum` | Define o maior valor permitido; o padrão é `99` e o teto é `999999`.                                           |
| `price_data.recurring`        | Transforma o item em recorrente e faz a sessão nascer em `mode: subscription`.                                 |

## 3. Personalize a tentativa de compra

Os parâmetros abaixo pertencem à sessão e podem mudar em cada pedido:

| Necessidade               | Parâmetro                                                                        | Regra principal                                                                                             |
| ------------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Voltar ao seu site        | `success_url`, `cancel_url`                                                      | Use URLs absolutas `http(s)`. Ambas são opcionais.                                                          |
| Fixar um Customer         | `customer_id`                                                                    | O cadastro deve pertencer à mesma organização e ao mesmo ambiente.                                          |
| Pré-preencher o comprador | `customer_name`, `customer_email`, `customer_document`, `customer_document_type` | Sem `customer_id`, esses dados antecipam o formulário e ajudam a resolver o Customer na confirmação.        |
| Aplicar desconto          | `discount_id`                                                                    | O desconto precisa ser válido para a organização, o ambiente, a moeda e os itens.                           |
| Repassar tarifa           | `has_surcharge`                                                                  | Disponível somente em sessão de pagamento avulso.                                                           |
| Criar invoice             | `invoice_creation`                                                               | Em `payment`, materializa invoice depois do pagamento; em `subscription`, invoices já fazem parte do ciclo. |
| Alterar o botão           | `submit_type`                                                                    | Aceita `auto`, `pay`, `subscribe`, `book` ou `donate`.                                                      |
| Relacionar o pedido       | `metadata`                                                                       | Objeto livre `string → string`, ecoado nos webhooks.                                                        |
| Registrar aquisição       | `marketing_attribution`                                                          | Preserva o primeiro contexto de campanha da compra.                                                         |

### Exemplo de compra avulsa personalizada

Este request fixa um Customer, aplica desconto, permite alterar a quantidade,
repassa a tarifa e cria uma invoice depois do pagamento:

```bash theme={"theme":"css-variables"}
curl -X POST "https://api.chargefy.io/v1/checkout-sessions" \
  -H "Authorization: Bearer {{API_KEY}}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: checkout-order-8f4c2a" \
  -d '{
    "cancel_url": "https://meusite.com/carrinho",
    "customer_id": "cus_R7mK2pQ9xW4nT8vL",
    "discount_id": "disc_6Kd2pQ9xW4nT8vLR",
    "has_surcharge": true,
    "invoice_creation": true,
    "line_items": [
      {
        "adjustable_quantity": {
          "enabled": true,
          "maximum": 5,
          "minimum": 1
        },
        "price_id": "price_w9A2hszZXxVwxRaG",
        "quantity": 1
      }
    ],
    "metadata": {},
    "submit_type": "pay",
    "success_url": "https://meusite.com/pedido/confirmado?session_id={CHECKOUT_SESSION_ID}"
  }'
```

O placeholder `{CHECKOUT_SESSION_ID}` é substituído pelo `cs_*` da sessão antes
do redirect. Use o ID para mostrar o estado atual, mas não para liberar o pedido
sem webhook.

### Atribuição de marketing

Quando seu backend já recebeu a campanha, envie um snapshot tipado. A primeira
captura válida permanece associada à sessão; uma abertura posterior não a
substitui.

```json theme={"theme":"css-variables"}
{
  "attribution_id": "campaign-order-123",
  "click_ids": {
    "gclid": "EAIaIQobChMI2pQ9xW4nT8vL7mK3rF5sA1dC6eH9"
  },
  "landing_page_url": "https://meusite.com/oferta?utm_source=paid_search",
  "utm": {
    "campaign": "lancamento_2026",
    "medium": "paid_search",
    "source": "search"
  }
}
```

Envie esse objeto em `marketing_attribution`. Se a campanha chegar na própria
URL hospedada, a Chargefy também pode capturar UTMs e identificadores de clique
no primeiro carregamento.

<Tip>
  `metadata` serve para valores livres do seu sistema. Dados com significado
  próprio na Chargefy — como desconto, Customer, atribuição e URLs — devem usar
  seus parâmetros tipados.
</Tip>

## 4. Crie pagamentos recorrentes

O `mode` é derivado dos itens. Um Price recorrente ou
`price_data.recurring` cria uma sessão `subscription`; você não envia `mode`.

```bash theme={"theme":"css-variables"}
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_PBNzo3CF3vAZee7b",
          "recurring": {
            "interval": "month",
            "interval_count": 1
          },
          "unit_amount": 12990
        },
        "quantity": 1
      }
    ],
    "metadata": {},
    "payment_method_collection": "always",
    "subscription_data": {
      "metadata": {},
      "trial_period_days": 14,
      "trial_settings": {
        "end_behavior": {
          "missing_payment_method": "pause"
        }
      }
    },
    "success_url": "https://meusite.com/assinatura/confirmada?session_id={CHECKOUT_SESSION_ID}"
  }'
```

| Parâmetro                                | Opções                              | Uso                                                                    |
| ---------------------------------------- | ----------------------------------- | ---------------------------------------------------------------------- |
| `price_data.recurring.interval`          | `day`, `week`, `month`, `year`      | Unidade do ciclo.                                                      |
| `price_data.recurring.interval_count`    | inteiro                             | Quantos intervalos compõem cada ciclo.                                 |
| `subscription_data.trial_period_days`    | inteiro maior ou igual a `1`        | Trial contado a partir da confirmação.                                 |
| `subscription_data.trial_end`            | timestamp futuro                    | Fim exato do trial; não combine com `trial_period_days`.               |
| `subscription_data.cancel_at`            | timestamp futuro                    | Encerra a assinatura em uma data específica.                           |
| `subscription_data.cancel_at_period_end` | boolean                             | Encerra no fim do primeiro período; não combine com `cancel_at`.       |
| `subscription_data.trial_settings`       | `cancel`, `create_invoice`, `pause` | Ação ao fim do trial sem método de pagamento.                          |
| `payment_method_collection`              | `always`, `if_required`             | Controla se o checkout coleta cartão quando não há valor devido agora. |

`payment_method_collection` e `subscription_data` só são aceitos em sessões
recorrentes. `has_surcharge` só é aceito em sessões avulsas.

## 5. Entenda o que vem do Checkout Builder

A aparência e a política da página não fazem parte do request. A página usa a
configuração atual da organização quando o comprador abre a `url`.

| Configuração da organização | Efeito na sessão hospedada                                               |
| --------------------------- | ------------------------------------------------------------------------ |
| Identidade e template       | Aplica logo, cores, fonte, tema, bordas e composição.                    |
| Formas de pagamento         | Define se cartão, Pix e boleto aparecem.                                 |
| Dados adicionais            | Pode exigir documento, telefone ou endereço além do piso de cada método. |
| Parcelamento                | Mostra as opções válidas e o valor de cada parcela.                      |
| Códigos de desconto         | Permite que o comprador informe um código na página.                     |

Use [Configurar sua página de
checkout](/payments/configure-checkout-page) para alterar essas regras uma vez,
sem repetir configuração em cada sessão.

## 6. Redirecione o comprador

O botão do seu site chama uma rota do seu backend. Essa rota cria a sessão e
devolve somente a URL necessária para abrir o checkout:

```html theme={"theme":"css-variables"}
<button id="checkout-button" type="button">Ir para o pagamento</button>

<script>
  document
    .querySelector("#checkout-button")
    .addEventListener("click", async () => {
      const response = await fetch("/api/checkout", { method: "POST" });
      const session = await response.json();

      if (!response.ok) {
        showCheckoutError();
        return;
      }

      window.location.assign(session.url);
    });
</script>
```

Não crie a sessão diretamente no browser. Além de expor sua API key, isso tira
do backend o controle de preço, desconto, Customer e idempotência.

## 7. Prepare retorno e webhooks

`success_url` melhora a experiência do comprador, mas não confirma o dinheiro.
Pix e boleto podem concluir o formulário e continuar `unpaid` até a compensação.

| Evento                                     | Quando chega                              | O que fazer                                                            |
| ------------------------------------------ | ----------------------------------------- | ---------------------------------------------------------------------- |
| `checkout.session.completed`               | O comprador concluiu o checkout.          | Libere apenas se `payment_status` for `paid` ou `no_payment_required`. |
| `checkout.session.async.payment.succeeded` | Pix ou boleto foi pago depois.            | Inicie o fulfillment.                                                  |
| `checkout.session.async.payment.failed`    | A tentativa assíncrona falhou ou venceu.  | Encerre a tentativa sem entregar.                                      |
| `checkout.session.expired`                 | A sessão chegou ao prazo ou foi expirada. | Ofereça a criação de uma nova sessão.                                  |

No seu endpoint de webhook:

1. verifique a assinatura usando o corpo bruto;
2. deduplique pelo `event.id`;
3. confirme `data.object.payment_status`;
4. relacione a sessão ao pedido com seu `metadata`;
5. execute entrega ou ativação de forma idempotente;
6. responda `2xx` rapidamente e processe trabalho demorado fora da resposta.

Veja [Após receber com um Checkout](/payments/checkout-post-payment) para montar
a página de retorno e [Entregar pedidos](/payments/fulfill-orders) para tratar
reenvios sem duplicar efeitos.

## 8. Use Chargefy for Platforms quando aplicável

<Warning>
  Esta seção só se aplica a contas com o produto **Chargefy for Platforms**
  habilitado. Nesse produto, uma plataforma opera pagamentos para suas
  organizações filhas.
</Warning>

Use a API key da plataforma e envie o header `Organization` com a organização
filha que receberá o pagamento. Prices, Products, Customers e descontos usados
na sessão também precisam pertencer a ela.

```bash theme={"theme":"css-variables"}
curl -X POST "https://api.chargefy.io/v1/checkout-sessions" \
  -H "Authorization: Bearer {{API_KEY}}" \
  -H "Organization: org_5Nq8rT2wX7mK4pV9" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: checkout-order-8f4c2a" \
  -d '{
    "line_items": [
      {
        "price_id": "price_w9A2hszZXxVwxRaG",
        "quantity": 1
      }
    ],
    "metadata": {},
    "success_url": "https://plataforma.com/pedido/confirmado?session_id={CHECKOUT_SESSION_ID}"
  }'
```

Uma API key comum de organização não envia esse header: ela atua somente na
própria organização.

## 9. Teste antes de publicar

Crie a sessão com uma API key do ambiente de teste, abra a `url` retornada e
use dados do [Sandbox](/api-reference/sandbox).

| Cenário de cartão | Número             | Resultado esperado                                         |
| ----------------- | ------------------ | ---------------------------------------------------------- |
| Aprovação         | `4242424242424242` | A sessão termina com `payment_status: "paid"`.             |
| Recusa genérica   | `4000000000000002` | A sessão continua aberta para correção ou troca do cartão. |

Para Pix e boleto, use os e-mails determinísticos documentados no sandbox e
teste tanto confirmação imediata quanto resultado atrasado. Seu fluxo está
pronto quando o mesmo `cs_*` aparece na página de retorno, na consulta da API e
no webhook processado pelo backend.

## Erros comuns

| Situação                                                              | Resultado      |
| --------------------------------------------------------------------- | -------------- |
| `line_items` ausente ou vazio                                         | `400`          |
| `price_id` junto de `price_data`                                      | `400`          |
| `price_data` sem uma única origem de produto                          | `400`          |
| Moedas diferentes no mesmo array                                      | `400`          |
| Itens avulsos e recorrentes misturados                                | `400`          |
| `has_surcharge: true` em recorrência                                  | `400`          |
| `subscription_data` em pagamento avulso                               | `400`          |
| `payment_method_collection` em pagamento avulso                       | `400`          |
| Customer, Price, Product ou desconto de outra organização ou ambiente | `400`          |
| API key ausente, inválida ou sem escopo `write`                       | `401` ou `403` |
| Header `Organization` ausente ou inválido no Chargefy for Platforms   | `400` ou `403` |

Consulte [Criar uma sessão de
checkout](/api-reference/checkout-sessions/create) para o contrato completo de
todos os parâmetros e respostas de erro.

## Próximos passos

<CardGroup cols={2}>
  <Card title="Entender Checkout Sessions" icon="cart-shopping" href="/payments/create-checkout-page">
    Veja origens, responsabilidades, estados e limites do objeto.
  </Card>

  <Card title="Configurar a página" icon="sliders" href="/payments/configure-checkout-page">
    Configure identidade, métodos, campos obrigatórios e parcelamento.
  </Card>

  <Card title="Após receber com um Checkout" icon="arrow-right-to-bracket" href="/payments/checkout-post-payment">
    Conecte a página de retorno aos webhooks e ao fulfillment.
  </Card>

  <Card title="Referência da API" icon="brackets-curly" href="/api-reference/checkout-sessions/create">
    Consulte o schema exato do `POST /v1/checkout-sessions`.
  </Card>
</CardGroup>
