Skip to main content
Este guia leva seu SaaS do plano ao segundo mês cobrado sozinho. Você modela o plano uma vez, o cliente assina uma vez — e a partir daí cada renovação abre a fatura, cobra o cartão salvo e avisa seu sistema por evento. Recorrência de verdade não é um cron passando cartão: as retentativas, a régua de cobrança e os eventos de ciclo já vêm prontos. Seu trabalho é reagir a meia dúzia de webhooks. A linha do tempo de um assinante com trial de 14 dias:
Como nos outros guias, tudo roda em test mode (ch_test_...), sem dinheiro real. Se esta é a sua primeira integração, faça antes o Aceitar o primeiro pagamento — ele deixa prontos a API key e o receiver de webhook que este guia reaproveita. Daqui em diante os exemplos mostram só o payload: o método e a rota ficam no título de cada bloco.

1. Modele os planos: preço recorrente, trial no preço

Plano de SaaS na Chargefy é um produto com preço recorrente. O mesmo request que você já conhece cria os dois — a diferença é o bloco recurring. E o trial pode morar no próprio preço: todo checkout desse plano já nasce com o período gratuito, sem configuração extra por venda.
POST /v1/products
A resposta traz o produto com o preço dentro — guarde o prices[0].id (price_LECZy65rvF8ws5V9 nos exemplos). Repita para o plano de cima, sem trial desta vez:
POST /v1/products
Esse é o price_W8pwrLwf2Mup6hd4 — vamos usá-lo no upgrade. Intervalos disponíveis: day, week, month e year (um plano anual é só outro preço no mesmo produto).

2. Venda a assinatura: o checkout faz o trabalho

Você não cria a assinatura na mão: cria uma checkout session com o preço recorrente, e a sessão nasce em mode: "subscription" automaticamente. O comprador preenche os dados, o cartão é salvo — e como o preço tem trial, nenhuma cobrança acontece agora.
POST /v1/checkout-sessions
Antes de redirecionar o usuário para a url da resposta, grave no seu banco a relação entre o usuário do app e o id da checkout session. Essa relação é o que permite reconhecer o usuário quando o webhook chegar. Quando o comprador conclui, chega o checkout.session.completed com payment_status: "no_payment_required" (trial: cartão salvo, nada cobrado) e dois campos que você deve gravar:
Na success_url, não trate o tempo entre esse evento e a liberação do acesso como falha. Mostre uma tela curta de ativação e consulte seu backend até a tentativa ficar pronta. Veja o fluxo completo em Após receber com um Checkout. A partir daqui, sub_SrDq4teYKmrQ3w8g é o contrato recorrente. Os campos dele que seu SaaS vai consultar (objeto completo):
Também dá para criar assinatura direto pela API (POST /v1/subscriptions com customer e items), sem checkout — útil em vendas assistidas e migrações. Veja Criar assinatura.

Vender com prazo

Nem toda assinatura renova para sempre. Plano anual entregue como um ano, curso em 12 mensalidades, contrato com vigência — nesses casos o término faz parte da venda, não é uma correção depois. Declare o prazo junto com a venda e a assinatura encerra sozinha na data. Sem lembrete no calendário, sem clique no dia certo, sem risco de cobrar de novo um cliente que já tinha combinado o fim. Pelo checkout, o prazo viaja no mesmo subscription_data que já carrega o trial:
Para “12 mensalidades e encerra”, o agendamento converte a contagem em data usando a cadência da assinatura — você não precisa calcular o vencimento nem lidar com fim de mês:
Terminar no prazo combinado não é cancelamento. canceled_at continua null numa assinatura com prazo declarado, e ela conta como ativa enquanto estiver faturando. Quem quer encerrar agora usa DELETE /v1/subscriptions/ {id}.

3. Do trial ao segundo mês: ninguém agenda nada

Sem cron, sem job, sem coluna next_charge_at no seu banco. A Chargefy cuida da régua e te avisa em cada passo:
  1. Dia 11subscription.trial.will.end chega 3 dias antes do fim do trial. É o gatilho pro e-mail de “seu período gratuito termina em 3 dias”.
  2. Dia 14 — o trial vira cobrança: a fatura do primeiro ciclo é criada e o cartão salvo é cobrado. Chegam invoice.paid e subscription.updated com status: "active".
  3. Dia 44 — o segundo mês cobra sozinho: nova fatura (billing_reason: "subscription_cycle"), cobrança no cartão padrão, período avançado. De novo invoice.paid e subscription.updated — agora com previous_attributes mostrando o current_period_end anterior.
  4. Dia 74, 104, 134… — repete, ciclo após ciclo, até alguém cancelar.
E se o trial terminar sem cartão salvo? trial_settings.end_behavior.missing_payment_method decide: create_invoice (padrão) gera a fatura mesmo assim e a assinatura pode ficar past_due; pause congela em paused até voltar com cartão; cancel encerra. Detalhes em Trial.

4. Libere e bloqueie acesso por eventos

O gate de acesso do seu SaaS é uma função do status da assinatura — e o status chega por webhook, então seu banco fica em sincronia sem polling. No mesmo receiver do guia anterior:
O mapa completo de status, na visão de quem libera acesso:

5. Cartão falhou? A régua de recuperação já vem pronta

É aqui que “um cron passando cartão” quebra — e a Chargefy não. Quando uma renovação é recusada:
  1. A assinatura vai para past_due e a fatura fica open. Você recebe invoice.payment.failed, e a fatura passa a expor o estado da régua: attempt_count (quantas tentativas a agenda consumiu) e next_payment_attempt (quando a próxima roda). Cada tentativa executada continua registrada em payments.data[].
  2. A Chargefy reprocessa a cobrança sozinha, nos dias definidos pela política de recuperação da organização — configurável em Configurações → Recuperação, com agenda recomendada de até 8 tentativas em 2 semanas ou passos personalizados. O assinante recebe um e-mail por tentativa que falhou, com a marca da organização e um link que troca o cartão e recobra a fatura na hora. Recuperou: volta para active e chega invoice.paid.
  3. Recusas que repetir não resolve — cartão perdido, roubado, número inválido — não são reapresentadas: a agenda continua viva (next_payment_attempt segue preenchido, attempt_count segue contando), esperando o cliente salvar um cartão novo. Salvou, a próxima tentativa executa com ele.
  4. Esgotou a janela: aplica-se a ação final configurada — marcar como não paga (padrão), manter em atraso, ou cancelar a assinatura. Em unpaid, a cobrança automática para, mas as faturas continuam abertas e cobráveis — e pagar qualquer fatura aberta reativa a assinatura.
O funcionamento completo da régua — agenda, contadores, recusas definitivas e métricas — está em Recuperação inteligente de receita. E quando a régua automática não resolve, a recuperação manual tem dois atalhos prontos:
  • Mande a fatura — toda invoice tem hosted_invoice_url, uma página de pagamento pronta para WhatsApp ou e-mail.
  • Ou mande direto a troca de cartão — um deep link do portal que já abre no formulário de novo cartão e reprocessa a fatura em aberto:
POST /v1/customer-portal-sessions
Quando o cliente conclui, o cartão novo vira o padrão e a fatura informada é cobrada nele.

6. Upgrade e downgrade com pró-rata

Mudar de plano é trocar o preço do item da assinatura — um POST, e a Chargefy calcula o pró-rata do período atual:
POST /v1/subscriptions/sub_SrDq4teYKmrQ3w8g
(si_Etg7CZEuk71HZVAW é o items.data[0].id da assinatura; price_W8pwrLwf2Mup6hd4 é o Plano Pro da seção 1. O preço novo precisa ter a mesma moeda e o mesmo intervalo.) O que acontece com o meio do ciclo depende de proration_behavior: A conta é a justa: upgrade no meio do mês credita o tempo não usado do plano antigo e cobra só o restante do ciclo no plano novo; downgrade gera crédito automático abatido das próximas faturas. Em trial, a troca não gera ajuste — o valor novo vale quando o trial acabar.
Upgrade que só pode valer depois de pago? Combine proration_behavior: "always_invoice" com payment_behavior: "pending_if_incomplete": a mudança fica retida em pending_update até a fatura de update ser paga. E para mostrar o valor do ajuste antes de aplicar, simule com Prévia de invoice. O passo a passo pelo dashboard está em Atualizando assinaturas ativas.

7. Portal do cliente: troca de cartão sem abrir chamado

O portal do cliente é a área de billing hospedada do seu SaaS: o cliente troca o cartão, corrige dados de cobrança, baixa segunda via de fatura e cancela a assinatura — com a sua marca, sem você construir tela nenhuma e sem ticket no suporte. Coloque um botão “Gerenciar assinatura” no seu app que cria uma sessão e redireciona:
POST /v1/customer-portal-sessions
Resposta
Redirecione para url na hora — o link é de uso único e vale por 1 hora. Com flow_data, a sessão abre direto na tarefa: payment_method_update (trocar cartão), customer_update (corrigir dados) ou subscription_cancel (cancelamento guiado, agendado pro fim do período já pago). Tudo que o cliente fizer no portal chega no seu backend pelos mesmos webhooks das seções anteriores.
Upgrade e downgrade de plano são uma decisão de pricing do seu produto — exponha os planos no seu app e aplique a troca com a chamada da seção 6. O portal cuida do resto do autoatendimento: cartão, dados, faturas e cancelamento. Sem backend, há ainda o link público do portal (login por e-mail) — veja Portal do cliente.

Checklist de produção

  1. Ambiente live: chave ch_live_..., endpoint de webhook live e planos recriados no live mode (dados de teste não migram) — o mesmo checklist do primeiro pagamento.
  2. Política de trial definida: dias de trial no preço e trial_settings.end_behavior escolhido conscientemente.
  3. Régua de past_due decidida: bloquear na hora ou dar período de graça — e o e-mail de cobrança pronto para o invoice.payment.failed.
  4. Gate por evento, não por palpite: acesso sai de subscription.updated, nunca de um cálculo local de datas.

Próximos passos

Trial a fundo

Trial por dias ou data fixa, coleta de cartão e as três políticas de fim de trial.

Atualizando assinaturas ativas

O mesmo upgrade/downgrade da seção 6, feito pelo dashboard e com prévia visual.

Como ativar assinaturas incompletas

Assinatura criada sem trial: como ela sai de incomplete para active.

Migrar assinaturas

Já fatura em outro sistema? Importe as assinaturas ativas sem cobrar duas vezes.