Assinaturas

Visão geral

O recurso de Assinaturas (Subscriptions) gerencia cobranças recorrentes: planos mensais/anuais,

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

{
  "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": "[email protected]" },
  "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,
  "discount": null,
  "discounts": 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": { }
}

Valores em centavos. items[].unitPrice é inteiro em centavos (ex.: 9900 = R$ 99,00). O objeto currentCycle reflete o ciclo de cobrança vigente; a recorrência (frequência, dia, trial) fica sob billing. Não há um campo amount/card/name no topo do objeto.

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
unpaidRetentativas esgotadas sem pagamento
pausedPausada (não cobra até ser retomada)
canceledCancelada — não gera novos ciclos

Ciclo de Vida

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

Cancelar, pausar e retomar são POST em sub-rotas (/cancel, /pause, /resume) e retornam a assinatura atualizada (200 OK). Não há DELETE para assinaturas.

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

Não existem os eventos subscription.renewal/subscription.reactivated/subscription.expired. Cada ciclo cobrado gera uma transação com seus próprios eventos (transaction.approved/failed). A lista completa está no Catálogo de Eventos.

Sempre verifique a assinatura do webhook antes de processar — veja Verificando Assinaturas de Webhook.

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.

How is this guide?

On this page