> ## 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.

# Confirm a Checkout Session

> Confirma uma checkout session.

Endpoint público de confirmação. Usado pelo **browser do comprador** (na hosted page ou no seu frontend custom) para concluir a sessão de compra. A chamada confirma a `checkout.session`; a Chargefy resolve o customer, confirma a cobrança server-side pelo lifecycle de `payment_intent` e atualiza a session.

Para PIX e boleto, `complete` significa que o comprador fechou o formulário e recebeu os dados de pagamento. A confirmação financeira chega de forma assíncrona via webhook [`checkout.session.async.payment.succeeded`](/api-reference/webhooks/checkout.session.async.payment.succeeded). Para cartão, o `payment_status` pode virar `paid` na própria resposta, mas webhooks continuam sendo a fonte confiável para fulfillment.

<Tip>
  A confirmação da session não expõe nem exige IDs internos de processamento.
  Para reconciliar, use a `checkout.session`, o `payment_intent` relacionado
  quando aplicável e os webhooks.
</Tip>

## Autenticação

Nenhuma. O `client_secret` na URL é a credencial.

## Parâmetros de caminho

<ParamField path="client_secret" type="string" required>
  Secret opaco da checkout session, retornado no campo `client_secret` do
  create.
</ParamField>

## Attributes

<ParamField body="boleto_due_date" type="string">
  Data de vencimento do boleto (`YYYY-MM-DD`). Padrão: 3 dias depois da
  confirmação. Aplica só quando `payment_method: "boleto"`.
</ParamField>

<ParamField body="card_brand" type="string">
  Bandeira do cartão (`visa`, `mastercard`, `elo`, etc). Usado pra cálculo de
  juros — opcional, a Chargefy infere quando ausente.
</ParamField>

<ParamField body="card_id" type="string">
  Cartão já salvo **que pertence a este comprador**. Alternativa ao `token_id`
  para `credit_card`. A propriedade do cartão é validada antes de usar: um
  `card_id` que não pertence ao comprador é recusado. Prefira `token_id` no
  fluxo padrão.
</ParamField>

<ParamField body="customer_billing_address" type="object">
  Endereço de cobrança. **Obrigatório para `boleto`** e também quando a sessão
  tem `require_billing_address: true`. Para boleto, exige endereço brasileiro
  completo: `city`, `country` (`"BR"`), `neighborhood`, `number`, `postal_code`,
  `state` (UF de 2 letras) e `street`.
</ParamField>

<ParamField body="customer_document" type="string">
  CPF ou CNPJ do comprador. **Obrigatório para `boleto`** e quando a sessão
  exige documento (`require_document: true`, padrão da organização). Caso
  contrário, opcional. Usado na emissão de boleto e na identificação fiscal.
</ParamField>

<ParamField body="customer_document_type" type="string">
  `cpf` ou `cnpj`. Opcional, acompanha `customer_document`.
</ParamField>

<ParamField body="customer_email" type="string" required>
  Email do comprador. Sempre obrigatório.
</ParamField>

<ParamField body="customer_name" type="string" required>
  Nome completo do comprador. Sempre obrigatório.
</ParamField>

<ParamField body="customer_details" type="object">
  Dados do comprador coletados na hosted page.

  <Expandable title="Campos de customer_details">
    <ParamField body="phone" type="string">
      Telefone do comprador. Obrigatório quando a sessão tem
      `require_phone: true`; usado na identidade de pagamento e no registro de
      boleto quando aplicável.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="discount_code" type="string">
  Cupom de desconto aplicado pelo comprador.
</ParamField>

<ParamField body="installments" type="integer" default="1">
  Número de parcelas (1–12). Aplica só com `credit_card`.
</ParamField>

<ParamField body="payment_method" type="string" required>
  Um de: `pix`, `boleto`, `credit_card`, `no_payment_required`.
  `no_payment_required` só vale para trial de assinatura criado com
  `payment_method_collection: "if_required"`. Os demais métodos devem estar em
  `payment_method_types` da sessão (caso contrário `400`).
</ParamField>

<ParamField body="token_id" type="string">
  Token de uso único do cartão, gerado client-side. **Caminho recomendado** para
  `credit_card`: a Chargefy associa o token ao comprador e conclui a cobrança
  server-side, inclusive salvando o cartão de forma reutilizável para
  assinaturas. **Veja [tokenização](#tokenizacao-do-cartao) abaixo.**
</ParamField>

## Campos obrigatórios por método

O comprador sempre informa **nome e email**. O boleto, por exigência do meio de pagamento, também precisa de **endereço** e **documento**.

Além disso, a política de checkout da sessão pode tornar obrigatórios o documento, o telefone e o endereço para **qualquer** método — campos `require_document`, `require_phone` e `require_billing_address` da sessão (herdados da organização no create). A política só **adiciona** exigências sobre o piso do método; nunca remove uma exigência do meio de pagamento. O telefone, quando exigido, vem em `customer_details.phone`.

| Método                | Campos obrigatórios (piso do meio de pagamento)                                      |
| --------------------- | ------------------------------------------------------------------------------------ |
| `credit_card`         | `customer_name`, `customer_email`, `token_id` (ou `card_id` do próprio comprador)    |
| `pix`                 | `customer_name`, `customer_email`                                                    |
| `boleto`              | `customer_name`, `customer_email`, `customer_billing_address`, `customer_document`   |
| `no_payment_required` | `customer_name`, `customer_email`; apenas para trial de assinatura sem cobrança hoje |

Faltar um campo exigido (pelo método ou pela política da sessão) retorna `422`.

## Três variantes

### (a) PIX

Mais simples: só nome e email. A resposta traz `payment_data.qr_code` (string EMV pra colar no app do banco) e `payment_data.qr_code_url` (PNG hospedado).

<RequestExample>
  ```bash cURL theme={}
  curl -X POST "https://api.chargefy.io/v1/checkout-sessions/public/{{CLIENT_SECRET}}/confirm" \
    -H "Content-Type: application/json" \
    -d '{
      "customer_email": "nome@email.com",
      "customer_name": "Cliente",
      "payment_method": "pix"
    }'
  ```
</RequestExample>

### (b) Boleto

Exige endereço brasileiro completo (FEBRABAN), opcionalmente com data de vencimento custom. A resposta traz `payment_data.barcode`, `payment_data.digitable_line` e `payment_data.pdf_url`.

<RequestExample>
  ```bash cURL theme={}
  curl -X POST "https://api.chargefy.io/v1/checkout-sessions/public/{{CLIENT_SECRET}}/confirm" \
    -H "Content-Type: application/json" \
    -d '{
      "customer_billing_address": {
        "city": "São Paulo",
        "country": "BR",
        "neighborhood": "Centro",
        "number": "100",
        "postal_code": "01001-000",
        "state": "SP",
        "street": "Rua Exemplo"
      },
      "customer_document": "12345678901",
      "customer_email": "nome@email.com",
      "customer_name": "Cliente",
      "payment_method": "boleto"
    }'
  ```
</RequestExample>

### (c) Cartão de crédito

Caminho padrão: envie `token_id` (token de uso único gerado client-side — nunca envie número de cartão direto pra esse endpoint). A Chargefy associa o token ao comprador e cobra server-side; a cobrança pode ser autorizada na hora e `payment_status: "paid"` na resposta indica sucesso. Para um cartão já salvo que pertence a este comprador, use `card_id` no lugar de `token_id` — a propriedade é validada antes de cobrar.

<RequestExample>
  ```bash cURL theme={}
  curl -X POST "https://api.chargefy.io/v1/checkout-sessions/public/{{CLIENT_SECRET}}/confirm" \
    -H "Content-Type: application/json" \
    -d '{
      "customer_email": "nome@email.com",
      "customer_name": "Cliente",
      "payment_method": "credit_card",
      "token_id": "{{CARD_TOKEN}}"
    }'
  ```
</RequestExample>

### (d) Trial sem cartão

Use `payment_method: "no_payment_required"` quando a sessão de assinatura foi
criada com trial e `payment_method_collection: "if_required"`. A confirmação
cria a assinatura em trial, não cria cobrança no momento e retorna
`payment_status: "no_payment_required"`.

<RequestExample>
  ```bash cURL theme={}
  curl -X POST "https://api.chargefy.io/v1/checkout-sessions/public/{{CLIENT_SECRET}}/confirm" \
    -H "Content-Type: application/json" \
    -d '{
      "customer_email": "nome@email.com",
      "customer_name": "Cliente",
      "payment_method": "no_payment_required"
    }'
  ```
</RequestExample>

#### Tokenização do cartão

A Chargefy **não aceita número de cartão em texto plano** neste endpoint. O `token_id` precisa ser um token de uso único gerado client-side por uma das duas vias:

* **Hosted page** (recomendado) — você redireciona o comprador pra `resposta.url` e o formulário de cartão da Chargefy tokeniza, confirma e devolve em `success_url`. Sem PCI no seu lado.
* **Frontend custom** — tokenize o cartão no browser com um fluxo client-side compatível e envie somente o token em `token_id`. O cartão nunca deve tocar seu servidor; a Chargefy associa o token ao comprador e conclui server-side.

## Resposta

Retorna o DTO completo da sessão **com `payment_data` preenchido** conforme o método.

A leitura canônica de display details para métodos assíncronos (PIX, boleto)
é `next_action` — um formato tipado com union discriminada por `type`.
`payment_data` permanece preenchido por compatibilidade durante a transição;
novas integrações devem ler `next_action`.

### PIX

<ResponseExample>
  ```json 200 theme={}
  {
    "id": "id_111",
    "object": "checkout.session",
    "...": "outros campos do DTO",
    "amount_total": 19990,
    "client_secret": "...",
    "currency": "brl",
    "invoice_creation": false,
    "mode": "payment",
    "next_action": {
      "pix_display_qr_code": {
        "expires_at": "2026-05-03T19:01:00Z",
        "qr_code": "00020126360014BR.GOV.BCB.PIX0114+5511...",
        "qr_code_url": "https://api.chargefy.io/qr/abc123.png"
      },
      "type": "pix_display_qr_code"
    },
    "payment_data": {
      "expiration_date": "2026-05-03T19:01:00Z",
      "payment_method": "pix",
      "qr_code": "00020126360014BR.GOV.BCB.PIX0114+5511...",
      "qr_code_url": "https://api.chargefy.io/qr/abc123.png",
      "status": "pending"
    },
    "payment_method_collection": "always",
    "payment_status": "unpaid",
    "status": "complete",
    "url": "https://pay.chargefy.io/session/..."
  }
  ```
</ResponseExample>

### Boleto

<ResponseExample>
  ```json 200 theme={}
  {
    "...": "campos do DTO",
    "invoice_creation": false,
    "next_action": {
      "boleto_display_details": {
        "barcode": "23791234567890123456789012345678901234567890",
        "expires_at": "2026-05-10",
        "hosted_voucher_url": "https://api.chargefy.io/boletos/abc123.pdf",
        "number": "23793.38128 60082.345678 90000.123456 7 89230000019990",
        "pdf": "https://api.chargefy.io/boletos/abc123.pdf"
      },
      "type": "boleto_display_details"
    },
    "payment_data": {
      "barcode": "23791234567890123456789012345678901234567890",
      "boleto_url": "https://api.chargefy.io/boletos/abc123.pdf",
      "digitable_line": "23793.38128 60082.345678 90000.123456 7 89230000019990",
      "due_date": "2026-05-10T03:00:00Z",
      "payment_method": "boleto",
      "status": "pending"
    },
    "payment_method_collection": "always",
    "payment_status": "unpaid",
    "status": "complete"
  }
  ```
</ResponseExample>

### Cartão de crédito (sucesso)

<ResponseExample>
  ```json 200 theme={}
  {
    "...": "campos do DTO",
    "invoice_creation": false,
    "next_action": null,
    "payment_data": {
      "installments": 3,
      "payment_method": "credit_card",
      "status": "succeeded"
    },
    "payment_method_collection": "always",
    "payment_status": "paid",
    "status": "complete"
  }
  ```
</ResponseExample>

### Trial sem cartão

<ResponseExample>
  ```json 200 theme={}
  {
    "...": "campos do DTO",
    "invoice_creation": false,
    "next_action": null,
    "payment_data": null,
    "payment_method_collection": "if_required",
    "payment_status": "no_payment_required",
    "status": "complete",
    "subscription": "sub_123"
  }
  ```
</ResponseExample>

## Webhooks disparados

| Quando                         | Evento                                                                                                         |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| Imediatamente após confirm     | [`checkout.session.completed`](/api-reference/webhooks/checkout.session.completed)                             |
| PIX/boleto compensados (async) | [`checkout.session.async.payment.succeeded`](/api-reference/webhooks/checkout.session.async.payment.succeeded) |
| Boleto vencido / PIX expirou   | [`checkout.session.async.payment.failed`](/api-reference/webhooks/checkout.session.async.payment.failed)       |
| Cobrança concluída             | [`payment.intent.succeeded`](/api-reference/webhooks/payment.intent.succeeded)                                 |
| Cobrança falhou                | [`payment.intent.failed`](/api-reference/webhooks/payment.intent.failed)                                       |

## Erros

| HTTP | Razão                                                                                                            |
| ---- | ---------------------------------------------------------------------------------------------------------------- |
| 400  | `client_secret` ausente; `payment_method` não está em `payment_method_types` da sessão                           |
| 400  | Campos obrigatórios do comprador faltando (`customer_name`/`customer_email`)                                     |
| 400  | `customer_billing_address` faltando ou incompleto quando `payment_method: "boleto"`                              |
| 400  | `token_id` (ou `card_id`) faltando quando `payment_method: "credit_card"`                                        |
| 400  | `card_id` não pertence a este comprador                                                                          |
| 400  | `installments` excede o máximo permitido pelo valor da sessão                                                    |
| 402  | Cartão recusado pelo emissor (`card_error`)                                                                      |
| 403  | Sessão não está em `status: "open"` (já confirmada, expirou ou foi soft-deletada)                                |
| 404  | Checkout session não encontrada                                                                                  |
| 422  | `no_payment_required` usado fora de trial de assinatura com `payment_method_collection: "if_required"`           |
| 422  | Campo exigido faltando: documento para `boleto`, ou documento/telefone/endereço exigidos pela política da sessão |
| 422  | Cupom inválido; restrição do meio de pagamento (ex: endereço fora do Brasil para boleto)                         |

<ResponseExample>
  ```json 400 theme={}
  {
    "error": {
      "code": "invalid_request",
      "message": "customer_email is required to confirm this checkout session.",
      "param": "customer_email",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 402 theme={}
  {
    "error": {
      "code": "payment_failed",
      "message": "Payment method was declined.",
      "type": "card_error"
    }
  }
  ```

  ```json 403 theme={}
  {
    "error": {
      "code": "permission_denied",
      "message": "Checkout session is not open and cannot be confirmed.",
      "type": "authentication_error"
    }
  }
  ```

  ```json 404 theme={}
  {
    "error": {
      "code": "resource_missing",
      "message": "Checkout session not found.",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 422 theme={}
  {
    "error": {
      "code": "invalid_request",
      "message": "Missing required field(s) for boleto: document.",
      "param": "customer_document",
      "type": "invalid_request_error"
    }
  }
  ```
</ResponseExample>
