SelectwinSelectwin

Assinaturas - Visão Geral

Introdução

O recurso de Assinaturas (Subscriptions) gerencia cobranças recorrentes: planos mensais/anuais, trials, ciclos de cobrança, itens (variantes) e divisão de receita (splits). Cada assinatura agrupa um cliente, um ou mais itens recorrentes e um método de pagamento, e a Selectwin orquestra automaticamente as cobranças de cada ciclo, emitindo webhooks a cada mudança de status.

Modelo Selectwin-strict

O endpoint POST /v1/subscriptions é Selectwin-strict: o preço vem das variantes (var_...), nunca de valores manuais. Portanto:

  • Não existe campo amount no corpo da assinatura — o valor é sempre o snapshot da variante.
  • Cada item em items[] deve referenciar uma variante recorrente via variantId; você controla apenas quantity (e anotações). unitPrice/currency/pricingSchema são congelados a partir da variante.
  • Uma variante inexistente retorna variantNotFound (404); uma variante que não está precificada como recorrente retorna variantNotRecurring (422).

Os items devem referenciar variantes recorrentes (var_...; o prefixo legado prv_... também é aceito).

Estrutura do Objeto Assinatura

JSON
{
  "id": "subs_01hqzvabc",
  "status": "active",
  "currency": "BRL",
  "method": "credit",
  "type": "recurring",
  "currentCycle": {
    "id": "scy_01hqzvabc",
    "cycle": 1,
    "status": "paid",
    "startDate": "2026-04-01T00:00:00.000Z",
    "endDate": "2026-05-01T00:00:00.000Z",
    "dueDate": "2026-04-01T00:00:00.000Z",
    "billedAt": "2026-04-01T10:15:00.000Z",
    "updatedAt": "2026-04-01T10:15:00.000Z",
    "createdAt": "2026-04-01T00:00:00.000Z"
  },
  "customer": { "id": "cus_01hqzvabc", "firstName": "João", "lastName": "Silva", "email": "joao@example.com" },
  "billing": {
    "frequency": "monthly",
    "frequencyCount": 1,
    "endDate": null,
    "exactDay": null,
    "freeTrialDays": null,
    "autoRenew": true,
    "address": { "street": "Avenida Paulista", "number": "1000", "city": "São Paulo", "state": "SP", "postcode": "01310100", "country": "BR" }
  },
  "canceledAt": null,
  "cancellation": null,
  "discount": null,
  "discounts": null,
  "renewalTerms": null,
  "shippable": false,
  "shipping": null,
  "spplited": false,
  "splits": null,
  "items": [
    { "id": "sit_01hqzvabc", "name": "Premium Plan", "enabled": true, "pricingSchema": "recurring", "unitPrice": 9900, "quantity": 1, "currency": "BRL" }
  ],
  "callback": { "webhookUrl": "https://example.com/webhook", "active": true },
  "geolocation": null,
  "externalReference": "ORDER-123",
  "metadata": { "campaign": "launch" },
  "updatedAt": "2026-04-12T17:56:33.000Z",
  "createdAt": "2026-04-12T17:56:33.000Z",
  "merchant": { "name": "Seller Name", "merchantId": "bus_1234567890", "isSubAccount": false },
  "_links": { }
}

Status da Assinatura

StatusDescrição
pendingCriada, aguardando a confirmação da primeira cobrança
trialingEm período de teste (trial), antes da primeira cobrança efetiva
activeAtiva e em dia
pastdueCobrança de um ciclo falhou; em retentativa (ver régua de inadimplência)
unpaidRetentativas esgotadas sem pagamento; cancelada quando a carência acaba
pausedPausada (não cobra até ser retomada)
canceledCancelada — não gera novos ciclos

Régua de inadimplência

Quando a cobrança de um ciclo falha, a assinatura vai para pastdue e a cobrança é tentada de novo depois de um intervalo, até o teto de tentativas do ciclo (a primeira cobrança conta). Esgotadas as tentativas, ela vai para unpaid e, passada a carência, é cancelada (subscription.canceled).

RegraPadrãoA loja pode escolher
Tentativas por ciclo (a 1ª incluída)5de 2 a 10
Intervalo entre uma falha e a próxima tentativa24 hde 1 a 168 h
Carência em unpaid até cancelar7 diasde 0 a 30 dias

A loja ajusta a sua régua no painel (configurações de assinatura). Uma mudança vale para os ciclos que ainda não começaram a ser cobrados; se ela aperta a régua (menos tentativas, intervalo maior), vale também para a cobrança em andamento. Afrouxar nunca alcança uma cobrança em andamento: um ciclo que já está sendo cobrado segue, no máximo, com as tentativas e o intervalo que valiam na primeira tentativa dele. A tentativa que já estava agendada quando a régua mudou acontece. Na lista de ciclos, attempts e nextAttemptAt mostram onde cada ciclo está.

O que cada renovação cobra

Cada ciclo cobra os itens da assinatura − os cupons recorrentes. Uma assinatura que nasceu no checkout hospedado (a partir de 15/10/2026) cobra também o que as regras da renovação do plano diziam no momento da compra, guardadas em renewalTerms:

  • Frete (renewalTerms.shipping): o frete cotado no checkout (shippingAmount, em centavos) entra em cada renovação.
  • Desconto do método (renewalTerms.methodDiscount): discountPercentage% sobre itens + frete, só nas renovações pagas por discountMethod. Uma renovação paga por outro método, por exemplo no cartão depois de trocar o meio de pagamento, não leva o desconto.

As regras ficam congeladas na assinatura: mudar o plano depois não as altera. renewalTerms: null quer dizer que a assinatura não congelou regras (criada antes de 15/10/2026, pela API de assinaturas ou por um upsell), e as renovações dela cobram os itens − os cupons recorrentes.

Ciclo de Vida

stateDiagram-v2
    state "pending" as pending
    state "trialing" as trialing
    state "active" as active
    state "pastdue" as pastdue
    state "unpaid" as unpaid
    state "paused" as paused
    state "canceled" as canceled

    [*] --> pending: POST /v1/subscriptions
    pending --> trialing: variante com trial
    pending --> active: 1ª cobrança aprovada
    trialing --> active: fim do trial, cobrança aprovada
    active --> pastdue: cobrança falhou
    pastdue --> active: retentativa aprovada
    pastdue --> unpaid: retentativas esgotadas
    active --> paused: POST .../pause
    paused --> active: POST .../resume
    active --> canceled: POST .../cancel
    unpaid --> canceled
    canceled --> [*]

Recursos Disponíveis

RecursoMétodoEndpointDescrição
CriarPOST/v1/subscriptionsCria uma assinatura recorrente
ListarGET/v1/subscriptionsLista paginada de assinaturas
ConsultarGET/v1/subscriptions/{id}Detalhes de uma assinatura
CancelarPOST/v1/subscriptions/{id}/cancelCancela a assinatura (no fim do período ou imediatamente)
PausarPOST/v1/subscriptions/{id}/pausePausa a assinatura (não cobra até retomar)
RetomarPOST/v1/subscriptions/{id}/resumeRetoma uma assinatura pausada
CiclosGET/POST/v1/subscriptions/{id}/cyclesLista, consulta e reagenda ciclos
ItensGET/POST/PATCH/DELETE/v1/subscriptions/{id}/itemsGerencia os itens (variantes)
SplitsGET/POST/PATCH/DELETE/v1/subscriptions/{id}/splitsDivisão de receita por destinatário

Pausa e retomada

  • Pausar suspende o acesso à Área de Membros concedido por esta assinatura. Retomar devolve. O acesso que o comprador tem por outra compra não é tocado.
  • Retomar reinicia o período hoje. Um ciclo que venceu durante a pausa é cobrado uma vez, com vencimento hoje, e o seguinte vence um período depois. Os meses da pausa não são cobrados. Se uma renovação foi aprovada durante a pausa, a próxima cobrança fica para o fim do período que ela pagou.
  • Quem pausou importa no portal do cliente. O comprador só retoma pelo portal uma pausa feita por ele mesmo, e sem fatura em aberto. Uma pausa feita por você, pela API ou pelo painel, só você desfaz.

Data do próximo ciclo

O próximo ciclo mantém o dia de cobrança quando o pagamento atrasa pouco. Se a data calculada a partir do ciclo pago já tiver passado (pagamento meses depois do vencimento), o próximo período conta a partir do pagamento.

Webhooks Acionados

EventoDescrição
subscription.createdAssinatura criada
subscription.pendingCriada, aguardando a confirmação da primeira cobrança
subscription.trialingEntrou em período de trial
subscription.activeAssinatura ativada (em dia)
subscription.updatedAssinatura alterada (itens, splits, etc.)
subscription.pastdueCobrança de ciclo falhou; em retentativa
subscription.unpaidRetentativas esgotadas sem pagamento
subscription.pausedAssinatura pausada
subscription.canceledAssinatura cancelada

Melhores Práticas

  1. Use variantes recorrentes para os itens; o preço é definido na variante, não na assinatura.
  2. Reaja a webhooks (subscription.*) em vez de fazer polling — veja Proibição de Polling.
  3. Trate pastdue/unpaid notificando o cliente para atualizar o método de pagamento.
  4. Use externalReference/metadata para correlacionar com o seu sistema.
  5. Idempotência: envie X-Idempotency-Key ao criar — veja Idempotência.

Integração com Outros Recursos

  • Customers — a assinatura é associada a um cliente (customer.id ou dados inline).
  • Products / Variants — os itens referenciam variantes recorrentes (var_...).
  • Transactions — cada ciclo cobrado gera uma transação.
  • Coupons — aplicáveis via discounts[] (códigos de cupom, re-aplicados por ciclo).
  • Webhooks — notificações em tempo real de mudanças de status.

Atualizado em 17 de outubro de 2026

Preferências de cookies

Hoje o site usa só cookies essenciais: nenhuma ferramenta de medição ou de anúncios está ligada, e nada é compartilhado com terceiros. Se isso mudar, você decide aqui antes de qualquer coisa ser carregada.

  • Mantêm o site funcionando: segurança, a sua escolha sobre cookies e preferências como a versão da documentação. Não dependem de consentimento.

    Sempre ativos