iHubGamesiHubGamesdocs

Subscriptions

Subscriptions (visão geral)

Subscription é a representação de uma assinatura recorrente: contém o cliente, o valor cobrado por ciclo, o ciclo (mensal, anual, etc.) e quando a próxima cobrança vai acontecer. Toda Subscription é dona de uma sequência de Invoices — uma por ciclo.

Uma Subscription tipicamente nasce do Checkout de uma Offer recorrente (URL pública /o/seu-user/:slug), mas você também pode criar diretamente via POST /v2/subscriptions (útil pra migrar clientes de outro sistema, ou pra cenários B2B com assinatura standalone — sem Offer, com amount e ciclo definidos direto pelo Customer).

Subscription criada → nextBillingAt chega → cron gera Invoice → cliente paga → marca PAID
                                                ↓ (se não paga)
                                          status: OVERDUE / PAST_DUE
                                                ↓
                              retry baseado em daysBeforeDueToBill

Snapshot pattern

Quando você cria uma Subscription a partir de uma Offer (offerId: "off_xyz..."), a iHubGames copia amount, billingCycle, billingCycleCount e maxCycles da Offer pra dentro da Subscription. A partir daí, a Subscription tem vida própria — alterações posteriores na Offer não afetam essa Subscription.

Mais ainda: quando você edita uma Subscription via PATCH /v2/subscriptions/:id, as mudanças só valem a partir da próxima cobrança. Invoices já criadas (PENDING, PAID, OVERDUE) ficam congeladas com os valores que tinham no momento da criação.

Cenários comuns:

  • Aumentar valor: a próxima invoice gerada vai com o valor novo; a Invoice deste mês (já criada) mantém o valor antigo.
  • Mudar lateFeeValue: invoices futuras usam a nova multa; invoices que já estão vencidas mantêm a multa do momento em que foram geradas.
  • Mudar nextBillingAt: empurra ou antecipa a próxima cobrança. Não mexe nas Invoices já existentes.

Isso garante que o cliente nunca seja cobrado retroativamente — o histórico reflete o que foi acordado em cada momento.

Estados da Subscription

StatusO que significaAceita pause?Aceita resume?Próxima invoice?
TRIALPeríodo de teste em andamento (definido por trialDays da Offer ou nextBillingAt setado pra futuro).✓—Quando nextBillingAt chegar
ACTIVEEm cobrança regular. Última invoice paga ou ainda dentro do prazo.✓—Sim, no nextBillingAt
PAST_DUEÚltima invoice venceu e não foi paga. Sub continua tentando.✓—Sim, conforme daysBeforeDueToBill
PAUSEDVocê pausou manualmente. Não gera novas invoices.—✓Não
CANCELEDEncerrada manualmente via POST /:id/cancel. Final.——Não
EXPIREDEncerrada automaticamente por atingir maxCycles ou expiresAt. Auto-transição (dispara subscription.expired). Final.——Não

Pause vs cancel:

  • Pause (POST /:id/pause) — para temporariamente. Pode reativar via POST /:id/resume; se nextBillingAt já está no passado, ele é reagendado pro próximo ciclo a partir de agora.
  • Cancel (POST /:id/cancel) — final. Cancela todas as invoices PENDING, OVERDUE e DRAFT da subscription em transação atômica.

Cancele quando o cliente saiu de vez. Pause quando ele pode voltar.

Ciclo de cobrança

A iHubGames roda um job de billing recorrente que processa todas as Subscriptions com nextBillingAt chegando.

daysBeforeDueToBill (default 5) — quantos dias antes do vencimento o sistema gera a Invoice. Default: 5. Range: 0–60.

Ex: se nextBillingAt é dia 25, com daysBeforeDueToBill: 5, a Invoice é criada dia 20 com dueDate 25. O cliente recebe a fatura, tem 5 dias pra pagar.

daysBeforeDueToNotify (default 3) — quantos dias antes do vencimento o sistema envia notificação de lembrete (se notificações estiverem habilitadas).

Fluxo do cron:

  1. Cron acorda → busca as Subscriptions com nextBillingAt <= now + daysBeforeDueToBill e status ACTIVE/TRIAL, e gera uma nova Invoice com dueDate = nextBillingAt.
  2. Cliente final recebe notificação e tem até dueDate pra pagar.
  3. Quando a Invoice é PAGA: Invoice → PAID; a Subscription avança currentCycle (+1) e recalcula nextBillingAt para o próximo ciclo (+1 mês, +1 ano, etc). Se currentCycle >= maxCycles (ou nextBillingAt > expiresAt), a Subscription vira EXPIRED (dispara subscription.expired).
  4. Se não paga até dueDate: Invoice → OVERDUE, Subscription → PAST_DUE (dispara subscription.past_due). Multa e juros aplicam (se configurados). Ao pagar depois, volta pra ACTIVE.

O ciclo só avança no pagamento — o cron apenas emite a fatura. Uma Subscription PAST_DUE não gera nova fatura até a anterior ser quitada.

Multas e juros

Quando uma Invoice fica em atraso, a iHubGames pode aplicar multa única + juros diários proporcionais automaticamente.

lateFeeType — tipo de multa:

  • NONE (default) — sem multa.
  • FIXED — multa em valor absoluto. lateFeeValue em centavos. Ex: lateFeeValue: 500 = R$ 5,00 de multa.
  • PERCENTAGE — multa percentual sobre o valor da invoice. lateFeeValue é o percentual cru (ex: 5 = 5%, 10 = 10%). Máximo: 100.

interestRatePerMonth — juros mensais aplicados proporcionalmente por dia de atraso. Percentual cru ao mês. Ex: interestRatePerMonth: 1 = 1% ao mês = ~0,033% ao dia. Máximo: 100.

⚠️ Atenção: quando lateFeeType: "PERCENTAGE", lateFeeValue: 5 é 5%. Quando lateFeeType: "FIXED", lateFeeValue: 500 é R$ 5,00. Não confunda os dois — confira o tipo antes de mandar.

A multa/juro é aplicada apenas em invoices que entram em OVERDUE. Cada attempt da Invoice carrega o lateFeeApplied e interestApplied no momento da tentativa.

maxCycles vs expiresAt

Tem duas formas de fazer uma Subscription terminar sozinha:

maxCycles — limite numérico. Ex: maxCycles: 12 com billingCycle: "MONTHLY" = anual parcelado em 12 cobranças, depois encerra. Cron cancela a Subscription após a 12ª cobrança gerada.

expiresAt — data fixa. Ex: expiresAt: "2026-12-31T23:59:59Z" = a Subscription termina nessa data, independente de quantos ciclos foram cobrados.

Pode usar os dois juntos — o que acontecer primeiro encerra. Ou só um, ou nenhum (Subscription "infinita", típica de SaaS recorrente sem fim).