docs

Assinaturas

Subscription (plano) vs CustomerSubscription (assinatura ativa) — billing intervals, trial, lifecycle e cancelamento.

A Zhex separa dois conceitos que muita plataforma confunde:

  • Subscription — o plano (template). Define billingInterval, trialPeriodDays, preço. Vive no produto.
  • CustomerSubscription — a assinatura ativa de um cliente sobre aquele plano. Tem status, datas de billing, ciclo atual.

Pense em Subscription como menu, e CustomerSubscription como pedido em andamento.

Onde cada um é gerenciado

RecursoConfiguraçãoAcesso
Subscription (plano)Dashboard → Produtos → PagamentoHoje só pelo dashboard. Endpoint público no roadmap.
CustomerSubscription (instância)API V1 — GET e cancel/v1/customer_subscriptions/...

A criação da CustomerSubscription é automática: quando o PaymentIntent em produto recorrente confirma com sucesso, a Zhex monta a assinatura usando o plano configurado no produto. Você não precisa de endpoint de "criar assinatura" — basta cobrar o produto.

Anatomia do plano (configurado no dashboard)

{
  id: 'sub_abc',
  productId: 'prd_xyz',
  name: 'Premium Mensal',
  billingInterval: 'MONTH',    // DAY | WEEK | MONTH | YEAR
  billingIntervalCount: 1,     // a cada 1 mês
  trialEnabled: true,
  trialPeriodDays: 7,
  isActive: true,
}

A combinação billingInterval × billingIntervalCount cobre todos os casos:

CobrançabillingIntervalbillingIntervalCount
DiáriaDAY1
SemanalWEEK1
QuinzenalWEEK2
MensalMONTH1
BimestralMONTH2
AnualYEAR1
A cada 2 anosYEAR2

CustomerSubscription — anatomia

{
  "id": "csub_abc",
  "object": "customer_subscription",
  "livemode": false,
  "customer": "cus_…",
  "subscription": "sub_…",
  "payment_intent": "pi_…",
  "status": "ACTIVE",
  "current_period_start": 1714060000,
  "current_period_end": 1716738400,
  "next_billing_date": 1716738400,
  "trial_start": null,
  "trial_end": null,
  "cancel_at": null,
  "canceled_at": null,
  "cancel_reason": null,
  "current_billing_cycle": 3,
  "created": 1707000000
}

Lifecycle de CustomerSubscription

A assinatura ativa de um cliente percorre uma máquina de estados:

StatusSignificadoAção
INCOMPLETEPaymentIntent da 1ª cobrança ainda não confirmouAguardar; libera quando vira ACTIVE
TRIALINGEm período de trial gratuitoConceder acesso; cobrança automática ao fim
ACTIVECobrando normalmenteConceder acesso
PAST_DUEÚltima cobrança falhou; em retryManter acesso por 7d (grace period)
UNPAIDEsgotou retries; aguardando pagamento manualBloquear acesso
CANCELEDEncerrada (final)Bloquear acesso, preservar histórico

Listar assinaturas

// todas
for await (const sub of zhex.customerSubscriptions.list({ limit: 100 }).autoPagingEach()) {
  /* … */
}

// filtrar por customer
for await (const sub of zhex.customerSubscriptions.list({
  customer: 'cus_…',
  status: 'ACTIVE',
  limit: 100,
}).autoPagingEach()) {
  /* … */
}

customerSubscriptions no SDK — verificação

Hoje o SDK @zhex/node cobre os recursos de cobrança direta (customers, paymentIntents, paymentMethods, refunds, tokens). Para customer_subscriptions use fetch direto enquanto adicionamos o resource ao SDK.

Cancelar uma assinatura

POST /v1/customer_subscriptions/:id/cancel — três modos:

curl -X POST https://prometheus.zhex.io/v1/customer_subscriptions/csub_…/cancel \
  -H "Authorization: Bearer $ZHEX_SECRET_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "requested_by_customer" }'
# Status vira CANCELED na hora.

cancel_at_period_end e cancel_at são mutuamente exclusivos. reason é livre — vai no audit trail.

Trial

Trial é configurado no plano (dashboard). Quando o cliente assina um produto recorrente com trial:

  1. CustomerSubscription nasce em TRIALING com trial_start/trial_end populados.
  2. Nenhuma cobrança acontece no período.
  3. No trial_end, a Zhex dispara o primeiro PaymentIntent automaticamente. Sucesso → ACTIVE. Falha → INCOMPLETE → retry → eventualmente UNPAID.

Liberação de acesso: trate TRIALING e ACTIVE como acesso liberado; PAST_DUE como grace period; UNPAID/CANCELED como bloqueado.

Webhooks

Hoje a API V1 emite os events de PaymentIntent que são side-effect das cobranças recorrentes:

  • payment_intent.succeeded — cobrança do ciclo N foi bem-sucedida
  • payment_intent.payment_failed — cobrança do ciclo N falhou (assinatura entra em PAST_DUE)
  • payment_intent.canceled — primeira cobrança cancelada antes de virar ativa

Para reagir a transições da própria CustomerSubscription (activated, trial_will_end, canceled), consulte o estado via GET /v1/customer_subscriptions/:id no momento que precisar — o vocabulário de events específico de subscription está no roadmap (customer_subscription.*).

Boas práticas

  • statement_descriptor curto e branded — aparece mensalmente no statement do cliente.
  • trialPeriodDays: 7 é o sweet spot. Menor que 3 não converte; maior que 14 aumenta churn de "esqueci de cancelar".
  • Trate falha de cobrança recorrente com email automático "atualize seu cartão" no payment_intent.payment_failed. Sem isso, churn involuntário sobe.
  • Nunca delete CustomerSubscription — sempre cancele. Histórico é receita LTV, financeiro e reconciliação.

Próximos passos

Esta página foi útil?

Atualizado em

Nesta página