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
| Status | O que significa | Aceita pause? | Aceita resume? | Próxima invoice? |
|---|---|---|---|---|
TRIAL | Período de teste em andamento (definido por trialDays da Offer ou nextBillingAt setado pra futuro). | ✓ | — | Quando nextBillingAt chegar |
ACTIVE | Em 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 |
PAUSED | Você pausou manualmente. Não gera novas invoices. | — | ✓ | Não |
CANCELED | Encerrada manualmente via POST /:id/cancel. Final. | — | — | Não |
EXPIRED | Encerrada 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
nextBillingAtjá está no passado, ele é reagendado pro próximo ciclo a partir de agora. - Cancel (POST /:id/cancel) — final. Cancela todas as invoices
PENDING,OVERDUEeDRAFTda 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, comdaysBeforeDueToBill: 5, a Invoice é criada dia 20 comdueDate25. 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:
- Cron acorda → busca as Subscriptions com
nextBillingAt <= now + daysBeforeDueToBille statusACTIVE/TRIAL, e gera uma nova Invoice comdueDate = nextBillingAt. - Cliente final recebe notificação e tem até
dueDatepra pagar. - Quando a Invoice é PAGA: Invoice →
PAID; a Subscription avançacurrentCycle(+1) e recalculanextBillingAtpara o próximo ciclo (+1 mês,+1 ano, etc). SecurrentCycle >= maxCycles(ounextBillingAt > expiresAt), a Subscription viraEXPIRED(disparasubscription.expired). - Se não paga até
dueDate: Invoice →OVERDUE, Subscription →PAST_DUE(disparasubscription.past_due). Multa e juros aplicam (se configurados). Ao pagar depois, volta praACTIVE.
O ciclo só avança no pagamento — o cron apenas emite a fatura. Uma Subscription
PAST_DUEnã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.lateFeeValueem 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%. QuandolateFeeType: "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).