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

# Ciclo de pagamento

> Como uma compra vira dinheiro liquidado: checkout session → payment intent → charge → invoice, e como os webhooks sinalizam cada transição.

Um pagamento na Chargefy não é um objeto único — é a colaboração de vários objetos, cada um com uma responsabilidade. Esta página é o **mapa que liga todos eles**: do clique de compra até o dinheiro liquidado. Os detalhes de cada objeto vivem nas páginas dedicadas; aqui o foco é **como eles se conectam** e **quem é fonte da verdade em cada etapa**.

<Info>
  **Um princípio acima de tudo: separe contexto de compra de resultado financeiro.**

  A experiência do comprador (a [`checkout.session`](/features/checkout-sessions)) é descartável e só reflete o que aconteceu. Quem é o **livro-razão** da cobrança é o [`payment_intent`](/features/payment-intents). Quem registra **cada tentativa concreta** de mover dinheiro é a [`charge`](/features/charges). Não trate a session — nem qualquer callback de frontend — como prova de pagamento.
</Info>

## Os objetos e seus papéis

| Objeto             | Responsabilidade                                                                                               | Quem cria                                   | Fonte da verdade para                                        |
| ------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------ |
| `checkout.session` | A tentativa de compra: coleta o comprador, mostra os métodos, confirma a escolha. Descartável e com expiração. | Seu backend (ou um clique em payment link). | Contexto e progresso da compra (`status`, `payment_status`). |
| `payment_intent`   | O ciclo de vida da cobrança: valor, moeda, método, status, próxima ação e desfecho.                            | Seu backend, a session ou uma invoice.      | Estado financeiro da cobrança.                               |
| `charge`           | Cada tentativa concreta de mover dinheiro. Somente leitura.                                                    | O sistema, ao confirmar um intent.          | O que foi cobrado e o que entrou.                            |
| `invoice`          | Documento de cobrança de assinatura (e de cobrança avulsa quando pedida).                                      | O ciclo de assinatura ou a API.             | Cobrança recorrente e contábil.                              |
| `payment_method`   | Instrumento salvo ou tokenizado.                                                                               | Tokenização no checkout ou setup intent.    | Como cobrar de novo no futuro.                               |

A Chargefy também registra movimentações internas de processamento para conciliação e suporte. Esses IDs internos **não** fazem parte do contrato público e não devem ser o objeto de sucesso da sua integração. Integre por `checkout.session`, `payment_intent`, `charge`, `invoice` e webhooks.

## O caminho completo

O fluxo padrão vai de uma **intenção de compra** até **dinheiro liquidado**, atravessando os objetos em ordem. Nem todo fluxo passa por todos — uma cobrança server-to-server pula a session; uma compra avulsa pula a invoice.

```mermaid theme={}
flowchart TD
  PL[payment_link] -- clique --> CS[checkout.session]
  API[seu backend] -- POST /v1/checkout-sessions --> CS
  CS -- confirm --> PI[payment_intent]
  API2[seu backend] -- POST /v1/payment-intents --> PI
  SUB[subscription] -- renova o ciclo --> INV[invoice]
  INV -- paga método salvo --> PI
  PI -- confirma --> CH[charge]
  PI -. nova tentativa .-> CH
  CH -- liquidou --> MONEY([dinheiro recebido])
```

| Origem                     | Como a cobrança nasce                                                                | Gera invoice?                                               |
| -------------------------- | ------------------------------------------------------------------------------------ | ----------------------------------------------------------- |
| Payment link               | Cada clique materializa uma `checkout.session` nova.                                 | Só se a session pedir (`invoice_creation=true`).            |
| Checkout session (backend) | Seu servidor cria a session sob demanda; a confirmação dispara o `payment_intent`.   | Recorrente: sempre. Avulso: só com `invoice_creation=true`. |
| Payment intent direto      | Server-to-server, sem session — você já sabe valor, customer e método.               | Não (a menos que o intent venha de uma invoice).            |
| Assinatura                 | Cada ciclo materializa uma `invoice`, que cobra o método salvo via `payment_intent`. | Sempre.                                                     |

<Note>
  **Compra avulsa não gera invoice por padrão.** Em `mode=payment`, o `payment_intent` é o documento financeiro. A invoice só materializa se a session foi criada com `invoice_creation=true`. Em assinatura, a invoice é sempre o documento de cada ciclo.
</Note>

## Síncrono vs. assíncrono

A grande bifurcação do ciclo é o **método de pagamento**. Cartão costuma resolver na hora; PIX e boleto ficam pendentes até a compensação chegar de forma assíncrona — e é aí que mora o erro mais comum de integração.

```mermaid theme={}
sequenceDiagram
  participant C as Comprador
  participant H as Página hospedada
  participant PI as payment_intent
  participant W as Webhook

  C->>H: escolhe método e confirma
  H->>PI: confirma a cobrança
  alt Cartão (síncrono)
    PI-->>H: status = succeeded
    PI->>W: payment.intent.succeeded
  else PIX / boleto (assíncrono)
    PI-->>H: status = pending + next_action
    H-->>C: exibe QR code / linha digitável
    C->>PI: paga depois (banco / app)
    PI->>W: payment.intent.succeeded
  end
```

| Método        | Confirmação | Estado intermediário                        | Quando o dinheiro entra                     |
| ------------- | ----------- | ------------------------------------------- | ------------------------------------------- |
| `credit_card` | Síncrona    | `processing`                                | Normalmente na própria resposta do confirm. |
| `pix`         | Assíncrona  | `pending` + `next_action` (QR code)         | Quando o comprador paga no banco/app.       |
| `boleto`      | Assíncrona  | `pending` + `next_action` (linha digitável) | Na compensação, dias depois.                |

<Warning>
  **`next_action` ausente não é pagamento confirmado.** Uma `checkout.session` de PIX/boleto pode ficar `status: "complete"` com `payment_status: "unpaid"` até a compensação. Quem confirma o sucesso é o webhook — nunca a resposta síncrona do confirm.
</Warning>

## Como os status se alinham

Cada objeto tem o próprio vocabulário de status. O quadro abaixo mostra como eles se movem **juntos** ao longo de uma compra. Os nomes são exatamente os do contrato público de cada objeto.

| Etapa                                                | `checkout.session.status` | `checkout.session.payment_status` | `payment_intent.status`                             | `charge.status`            |
| ---------------------------------------------------- | ------------------------- | --------------------------------- | --------------------------------------------------- | -------------------------- |
| Sessão criada                                        | `open`                    | `unpaid`                          | `requires_payment_method` / `requires_confirmation` | —                          |
| Comprador confirma (cartão)                          | `complete`                | `unpaid` → `paid`                 | `processing` → `succeeded`                          | `processing` → `succeeded` |
| Comprador confirma (PIX/boleto)                      | `complete`                | `unpaid`                          | `pending`                                           | `pending`                  |
| Pagamento assíncrono liquida                         | `complete`                | `paid`                            | `succeeded`                                         | `succeeded`                |
| Recusa de cartão                                     | `complete`                | `unpaid`                          | `requires_payment_method`                           | `failed`                   |
| Sessão sem confirmação por 24h                       | `expired`                 | `unpaid`                          | `canceled`                                          | —                          |
| Total zero (ex.: trial ou preço recorrente gratuito) | `complete`                | `no_payment_required`             | —                                                   | —                          |

<Note>
  `status` e `payment_status` da session são **eixos independentes**: `complete` significa que o comprador terminou o formulário; `paid` significa que o dinheiro entrou. Em PIX/boleto eles divergem temporariamente.
</Note>

### Ciclo de vida do payment intent

O `payment_intent` é o objeto que carrega o estado financeiro do início ao fim. Seus status:

```mermaid theme={}
stateDiagram-v2
  [*] --> requires_payment_method
  [*] --> requires_confirmation
  requires_payment_method --> requires_confirmation: método definido
  requires_confirmation --> processing: confirm (cartão)
  requires_confirmation --> pending: confirm (PIX / boleto)
  pending --> succeeded: comprador pagou
  processing --> succeeded
  processing --> requires_capture: capture_method = manual
  requires_capture --> succeeded: capture
  processing --> requires_payment_method: recusado
  pending --> canceled: cancel / expirou
  requires_capture --> canceled: cancel (estorna autorização)
  succeeded --> [*]
  canceled --> [*]
```

| Status                    | Significado                                                          |
| ------------------------- | -------------------------------------------------------------------- |
| `requires_payment_method` | Falta definir o método, ou o anterior falhou.                        |
| `requires_confirmation`   | Método definido; pronto para confirmar.                              |
| `pending`                 | Aguardando ação do comprador ou compensação assíncrona (PIX/boleto). |
| `processing`              | Pagamento em processamento.                                          |
| `requires_capture`        | Cartão autorizado; falta capturar (somente captura manual).          |
| `succeeded`               | Pagamento concluído.                                                 |
| `failed`                  | Pagamento falhou.                                                    |
| `canceled`                | Cobrança cancelada.                                                  |

<Note>
  **Boleto não pago expira sozinho.** Um intent de boleto que passa de `expires_at` sem compensar vira `canceled` automaticamente, com `cancellation_reason: "abandoned"`, e emite `payment.intent.canceled`.
</Note>

### Charge: cada tentativa

Um `payment_intent` pode produzir **mais de uma** `charge` (uma recusa seguida de nova tentativa). O intent aponta sempre a mais recente em `latest_charge`. A charge é somente leitura e percorre `pending → processing → succeeded | failed | canceled`. Use `paid`/`captured`/`amount_captured` para saber se o dinheiro de fato entrou — `status: "succeeded"` indica aprovação, não necessariamente captura.

## Invoices no ciclo recorrente

Para assinaturas, a `invoice` é o documento de cada ciclo: ela congela os valores, cobra o método salvo via `payment_intent` e registra o resultado contábil.

| Status          | Significado                                                                                                                                                                    |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `open`          | Criada, pagável e com valores congelados.                                                                                                                                      |
| `paid`          | Paga (ou marcada como paga fora do fluxo automático).                                                                                                                          |
| `void`          | Anulada.                                                                                                                                                                       |
| `uncollectible` | Baixa contábil **manual**: você marca a fatura como incobrável. Tentativas automáticas esgotadas deixam a fatura `open` e a assinatura `unpaid` — não vêm parar aqui sozinhas. |

O `billing_reason` explica por que a invoice nasceu:

| Valor                 | Quando aparece                                                                                                                                                    |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `subscription_create` | Criação da assinatura. Trial gratuito, desconto total ou preço recorrente gratuito podem vir com total `0`; caso contrário, vem com o valor da primeira cobrança. |
| `subscription_cycle`  | Renovação periódica (inclui a primeira cobrança real após um trial).                                                                                              |
| `subscription_update` | Mudança no meio do ciclo.                                                                                                                                         |
| `manual`              | Cobrança avulsa via API ou admin.                                                                                                                                 |

## Como os webhooks sinalizam cada transição

Webhooks são a **fonte confiável** para reagir ao ciclo. Cada transição importante emite um evento cujo `data.object` carrega o objeto público completo no estado atual; eventos de update trazem `data.previous_attributes` com os valores anteriores dos campos alterados. A lista completa está em [Webhook Events](/integrate/webhooks/events).

```mermaid theme={}
sequenceDiagram
  participant CF as Chargefy
  participant EP as Seu endpoint

  CF->>EP: checkout.session.created
  CF->>EP: payment.intent.created
  Note over CF,EP: comprador paga
  alt Cartão
    CF->>EP: charge.succeeded
    CF->>EP: payment.intent.succeeded
    CF->>EP: checkout.session.completed
  else PIX / boleto
    CF->>EP: checkout.session.completed (ainda unpaid)
    Note over CF,EP: compensação chega depois
    CF->>EP: charge.succeeded
    CF->>EP: payment.intent.succeeded
    CF->>EP: checkout.session.async.payment.succeeded
  end
```

Mapa de evento por fluxo:

| Fluxo                                       | Evento de referência para liberar produto  |
| ------------------------------------------- | ------------------------------------------ |
| Checkout hospedado concluído (cartão)       | `checkout.session.completed`               |
| Método assíncrono pago depois               | `checkout.session.async.payment.succeeded` |
| Método assíncrono falhou ou expirou         | `checkout.session.async.payment.failed`    |
| Cobrança direta paga                        | `payment.intent.succeeded`                 |
| Cobrança direta falhou                      | `payment.intent.failed`                    |
| Cobrança direta cancelada / boleto expirado | `payment.intent.canceled`                  |
| Tentativa de cobrança aprovada              | `charge.succeeded`                         |
| Tentativa de cobrança recusada              | `charge.failed`                            |
| Invoice de assinatura paga                  | `invoice.paid`                             |
| Invoice com tentativa falha                 | `invoice.payment.failed`                   |

<Warning>
  **Não libere produto, acesso ou serviço por callback de frontend.** O comprador pode fechar a aba antes do redirect, e PIX/boleto liquidam fora da página. Use o webhook como gatilho de fulfillment.
</Warning>

## Idempotência e reconciliação

Webhooks podem ser reenviados, e a mesma transição pode chegar mais de uma vez. Trate cada evento como **idempotente**:

<Steps>
  <Step title="Persista o id do evento">
    Guarde o `id` (`evt_*`) de cada webhook recebido. Se ele já foi processado, ignore — é uma reentrega.
  </Step>

  <Step title="Correlacione pelo seu próprio identificador">
    Use `metadata` (ex.: `metadata.order_id`) para ligar o evento ao seu pedido, sem depender de IDs internos da Chargefy. O `metadata` é ecoado em todos os webhooks do recurso.
  </Step>

  <Step title="Confirme o estado pelo objeto, não pelo evento">
    Em caso de dúvida, consulte o `payment_intent` ou a `charge` pelo `id` do payload para ler o estado atual antes de agir.
  </Step>
</Steps>

## Próximos passos

<CardGroup cols={2}>
  <Card title="Checkout Sessions" icon="cart-shopping" href="/features/checkout-sessions">
    A tentativa de compra e seus dois eixos de estado.
  </Card>

  <Card title="Payment Intents" icon="bullseye" href="/features/payment-intents">
    O livro-razão da cobrança ao longo do ciclo.
  </Card>

  <Card title="Charges" icon="receipt" href="/features/charges">
    Cada tentativa concreta de mover dinheiro.
  </Card>

  <Card title="Webhook Events" icon="bell" href="/integrate/webhooks/events">
    A lista completa de eventos e o formato do payload.
  </Card>
</CardGroup>
