Todas as datas internas do motor são normalizadas em UTC. O cálculo de ciclo é
determinístico: depende apenas da data de início e da regra de recorrência (
recurrence),
sem relógio externo. Em transport (body/query), datas sempre viajam em ISO 8601 com
offset — veja Convenções.A regra de recorrência
Cada assinatura tem umarecurrence (herdada do preço do plano ou informada inline). Ela é o
que define o tamanho do ciclo e o ponto de alinhamento das faturas.
São cinco campos, e cada um responde a uma pergunta diferente:
interval e unit andam juntos: 3 + month é trimestral. O anchor é o que decide se
“mensal” quer dizer todo dia 15 ou a cada 30 dias a partir de quando assinou — a diferença
está em Âncoras.
Âncoras
A âncora decide em que data cai o fim do ciclo atual — que é também o início do próximo ciclo e, por padrão, a data da próxima fatura.subscription_start — alinha pela data de início
subscription_start — alinha pela data de início
O próximo ciclo é simplesmente
início + intervalo. Preserva o horário (hora/min/seg) da
data de início.Exemplo (unit=month, interval=1, início em 15/jan/2026 10:00):Para meses curtos vale o clamp de fim de mês (veja abaixo): início em 31/jan
→ próximo fim em 28/fev (ou 29/fev em ano bissexto). Diferente do
day_of_month, o
subscription_start não re-ancora no dia original: cada passo avança a partir do fim do
ciclo anterior (já clampado), então depois de 28/fev o ciclo seguinte é 28/mar, depois 28/abr
— o dia “encolhe” para o menor mês atravessado e não volta a 31.day_of_month — todo dia X do mês (com clamp)
day_of_month — todo dia X do mês (com clamp)
Cobra sempre no dia
anchorDay. A primeira fatura recorrente cai ao menos um
intervalo à frente — nunca no mês corrente da assinatura. Isso evita ciclos curtos no
arranque.Exemplo (unit=month, interval=1, anchorDay=10):Ou seja: compra dia 5 com âncora no dia 10 não cobra no dia 10 do mesmo mês — vai
para o mês seguinte.
Se
anchorDay for maior que o número de dias do mês alvo, o motor ajusta para o
último dia do mês. anchorDay=31 em fevereiro vira 28/fev
(ou 29/fev em ano bissexto). E como o alinhamento re-ancora no dia original a cada
passo, não há drift: depois de 28/fev (31 clampado), o ciclo seguinte volta para
31/mar.end_of_month — sempre o último dia do mês
end_of_month — sempre o último dia do mês
Cobra sempre no último dia de cada mês do ciclo, qualquer que seja seu tamanho.Exemplo (
unit=month, interval=1, início em 10/jan):Assim como
day_of_month, a primeira fatura recorrente cai um intervalo à frente, nunca
no mês de início.Prepaid vs Postpaid
collectionTiming define onde, dentro do ciclo, a cobrança acontece.
prepaid (padrão)
Cobra no início de cada período. É o modelo clássico de SaaS/streaming: você paga
pelo período que está começando.
postpaid
Cobra no fim de cada período. Modelo de consumo/utility: você paga pelo período que
já passou.
collectionTimingno nível da assinatura —prepaid(default) oupostpaid.collectionTimingdentro da própriarecurrence— quando ausente, assumeprepaid(retrocompatibilidade com preços antigos que não tinham o campo).
Ausência do campo sempre significa
prepaid. Se você não definir nada, suas assinaturas
cobram no início do ciclo.Geração das faturas: just_in_time vs upfront
invoiceGenerationMode controla quantas faturas são criadas e quando.
Em
just_in_time, o número total de ciclos é limitado por maxCycles (quando informado);
sem maxCycles, a assinatura é considerada perpétua e o agendador continua gerando uma
fatura por ciclo indefinidamente.
Trial (período de teste)
trialSpec define um período inicial sem cobrança, e tem dois campos: durationDays, a duração
em dias, e requiresPaymentMethod, que decide se o cartão é exigido para o teste começar.
É o requiresPaymentMethod que muda o estado inicial. Com true e sem forma de pagamento, a
assinatura nasce incomplete — não trialing — e expira em cerca de 23 horas se nada for
anexado. Com false, o teste começa mesmo sem cartão, e a cobrança só é um problema no dia em que
o teste acaba. Assinatura criada pelo checkout sempre chega com forma de pagamento, então a
distinção não a alcança.
Durante o trial a assinatura fica no status trialing e nenhuma fatura é cobrada. Ao
final do trial, o motor gera a primeira fatura e a assinatura entra em cobrança normal.
O trialSpec no nível da assinatura tem precedência sobre o trial derivado de itens
baseados em plano (que vem do preço). Use o override no nível da assinatura quando o trial é
decidido fora do plano — por exemplo, checkout inline com itens sem preço associado.
Antecedência da cobrança
Uma fatura tem duas datas: quando ela é disparada para cobrança (chargeAt — o momento em
que abre e o boleto ou o PIX é criado) e quando vence (dueAt). A distância entre as duas
depende da forma de pagamento da assinatura:
Exemplo: uma fatura de boleto que vence em 20/jun é disparada para cobrança em 18/jun,
dando dois dias para o boleto circular antes do vencimento.
Esse
chargeAt ainda passa pela política de cobrança do lojista, configurada no painel: a
data pode ser deslocada para o próximo dia útil, e o horário fica dentro da janela
comercial definida, no fuso horário dele. O ajuste mexe apenas no chargeAt — o dueAt
contratual não muda.Dunning — o que acontece quando a cobrança falha
Quando uma cobrança recorrente falha, o motor entra em dunning (régua de inadimplência): ele decide se reagenda uma nova tentativa ou se desiste e aplica a política final. Por padrão são três retentativas, com 3, 5 e 7 dias de espera — e esgotá-las encerra a recobrança daquela fatura, não a assinatura. A assinatura segue outra régua: ficapast_due
desde a primeira falha e só é marcada unpaid por um verificador periódico, quando a fatura
vencida mais antiga passa do teto de inadimplência — 90 dias de atraso, por padrão. Todos
esses números são ajustáveis pelo lojista no painel — a API não os lê nem os escreve —, então uma
integração não deve tratá-los como fixos: leia o estado da assinatura em vez de prever datas.
Como a régua funciona
1
Cobrança falha
A fatura sai de
open e vai para past_due. A tentativa é registrada com a categoria da
recusa.2
Ainda há retentativas?
Se ainda restam tentativas e a recusa não é definitiva, o motor agenda a próxima
somando ao momento da falha o intervalo correspondente. A assinatura permanece ativa e a
fatura segue em
past_due.3
Tentativas esgotadas
Esgota ao usar todas as tentativas ou quando a recusa é definitiva — essa vai direto ao
desfecho, sem retentar.
4
Desfecho
A fatura permanece
past_due e sai da régua — nenhuma cobrança automática volta a tentá-la.
A assinatura continua past_due até a fatura vencida mais antiga completar o teto de
inadimplência (90 dias de atraso, por padrão); aí o verificador a marca unpaid — ou a
cancela, se o lojista configurou o cancelamento como desfecho.A transição padrão da assinatura quando a cobrança falha é
active/cobrando →
past_due (primeira falha) → unpaid (fatura vencida há mais que o teto — 90 dias por
padrão). Esgotar as retentativas não muda o status da assinatura — só encerra a recobrança
daquela fatura. Configurada para cancelar, o desfecho final é canceled em vez de unpaid.
Para os status detalhados da assinatura (
incomplete, trialing, active, past_due,
unpaid, paused, canceled, completed) veja
Assinaturas. Para os códigos de erro de chamadas à API
veja Erros.
Veja também
Assinaturas
Criar e gerenciar assinaturas — request completo com
recurrence, trialSpec,
collectionTiming e demais campos.Planos e preços
De onde a
recurrence é herdada quando a assinatura é baseada em plano.Faturas
Ciclo de vida de cada fatura —
open, past_due, paid e os campos chargeAt/dueAt.Visão geral de assinaturas
Conceitos do módulo de recorrência da Z2Pay.