SelectwinSelectwin

Criar Assinatura

POST /v1/subscriptions

Cria uma assinatura recorrente para um cliente. A precificação vem das variantes referenciadas em items (modelo Selectwin-strict — veja Visão Geral).

Requisição

Shell
curl -X POST "https://api.selectwin.io/v1/subscriptions" \
  -H "SelectKey: sk_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: 2dfc6a63-5df5-4900-baca-e49d91ef393e" \
  -d '{
    "customer": {
      "firstName": "João",
      "lastName": "Silva",
      "email": "joao@example.com",
      "document": { "type": "cpf", "number": "12345678901" },
      "telephone": { "countryCode": "55", "areaCode": "11", "number": "999999999" }
    },
    "payment": {
      "method": "credit",
      "card": { "id": "card_abc123" },
      "installments": 1
    },
    "items": [
      { "variantId": "var_abc123", "quantity": 1 }
    ],
    "billing": {
      "frequency": "monthly",
      "frequencyCount": 1,
      "exactDay": 10,
      "startDate": "2026-08-01",
      "endDate": null,
      "freeTrial": { "enabled": true, "days": 7 },
      "address": { "id": "addr_x" }
    },
    "discounts": [{ "code": "WELCOME5" }],
    "externalReference": "SUB-1001",
    "metadata": { "source": "checkout" }
  }'

Plano de N ciclos (cycles da variante)

Uma variante recorrente pode ser vendida com prazo — o 12× que aparece no catálogo e no portal (contractedCycles). Desde 16/set esse número é cumprido: até então ele era exibido e a assinatura renovava para sempre, cobrando o 13º.

  • O término é a data da N-ésima cobrança. O motor encerra quando o próximo vencimento passa do endDate, então o ciclo N ainda é cobrado e o N+1 não existe.
  • O trial não conta como ciclo: N ciclos são N cobranças, e o período de teste não cobra. A contagem começa na primeira cobrança de verdade.
  • Carrinho com planos de prazos diferentes vale o MENOR. Um item de 12× junto de um de 24× encerra em 12 — seguir cobrando um contrato que já se cumpriu seria cobrar por nada.
  • billing.endDate do corpo vence sempre. Quem o manda está declarando o prazo, e o catálogo não sobrepõe decisão do chamador.
  • ⚠️ Editar cycles na variante não mexe em assinatura já vendida. O prazo é congelado no dia da compra: o comprador contratou o que a tela mostrou.

Campos principais

CampoTipoObrigatórioDescrição
customerobjectSimCliente por id ou inline (firstName + lastName + email obrigatórios no caminho inline; document/telephone/gender/birthdate/additionalEmails opcionais)
items[]arraySim1 a 20 itens, cada um referenciando uma variante recorrente
items[].variantIdstringSimID da variante (var_...; também aceita o prefixo legado prv_...)
items[].quantityintegerNãoQuantidade, 1–999 999 (default 1) — o mesmo teto de adicionar/alterar um item. O preço vem da variante
items[].descriptionstringNãoAnotação do item (máx. 2048)
items[].externalReferencestringNãoSua referência do item
items[].metadataobjectNãoMetadados do item
payment.methodenumNãocredit, pix ou billet (default credit)
payment.cardobjectSim*Cartão por id, por token do navegador (Tokenização no navegador) ou inline. *Obrigatório para credit (cobrado automaticamente a cada ciclo)
payment.installmentsintegerNãoParcelas por cobrança, 1–21 (default 1)
payment.pix.expiresInMinutesintegerNãoExpiração do PIX por ciclo (15–525600)
payment.billet.expiresInDaysintegerNãoExpiração do boleto por ciclo (1–365)
billingobjectNãoAgenda de cobrança + endereço do pagador (espelha o bloco billing da resposta). Se omitido, usa os defaults de intervalo
billing.frequencyenumNãodaily, weekly, monthly, yearly (default monthly)
billing.frequencyCountintegerNãoMultiplicador da frequência, 1–365 (default 1). Ex.: billing.frequency=monthly + billing.frequencyCount=3 = a cada 3 meses
billing.exactDayintegerNãoDia fixo do mês para a cobrança (1–31)
billing.startDatestringNãoData de início (YYYY-MM-DD; default: hoje). A 1ª cobrança vence nesta data, então ela não pode ser anterior a hoje (dia de Brasília) → 422 subscriptionStartDateInPast
billing.endDatestringNãoData de término (YYYY-MM-DD). Omitindo, e se a variante do catálogo declarar um plano de N ciclos (productVariants.cycles, o "12×" que a loja exibe), o término é derivado: a data da N-ésima cobrança — ver abaixo
billing.freeTrialobjectNãoPeríodo de teste: { "enabled": true, "days": 7 }
billing.addressobjectNão*Endereço de cobrança (id ou inline). *Obrigatório para billet
autoRenewbooleanNãoRenovação automática (default true) — na raiz, não é agenda
discountsarrayNãoCupons por código ({ code }), máx. 20. Resolvidos e travados na criação; cada ciclo re-aplica o cupom conforme seu escopo (recurring reaplica a cada ciclo até o limite; firstCharge só no 1º ciclo). Mesmas regras de pilha da cobrança avulsa: código repetido → 422 couponAlreadyApplied; cupom isCumulative:false junto de outro → 422 couponNotCumulative. Aqui pesa mais, porque a pilha é congelada e reaplicada em todo ciclo
splits[]arrayNãoDivisão de receita por ciclo: { recipient, type, value } (máx. 20) — veja Splits
namestringNãoNome de exibição da assinatura
descriptionstringNãoDescrição livre (aceita, mas não persistida na leitura)
externalReferencestringNãoSua referência externa
metadataobjectNãoPares chave-valor livres. As chaves pixAutomatic, marketplaceApplicationFee, recurringPaymentWindow, sessionId e integrationId são da plataforma e são descartadas se vierem no corpo (o Pix Automático se pede por payment.pix.automatic)
shippingobjectNãoDados de entrega (assinaturas com produto físico)
callback.webhookUrlstring (url)NãoWebhook específico desta assinatura (callback.active default true)
onBehalfOfstringNãopublicId de uma sub-conta sua: cria a assinatura na sub-conta e cobra a taxa de aplicação da plataforma a cada ciclo (marketplace)

Resposta 201 Created

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",
    "birthdate": null,
    "gender": null,
    "document": { "type": "cpf", "number": "12345678901" },
    "telephone": { "countryCode": "55", "areaCode": "11", "number": "999999999", "line": "5511999999999" },
    "available": true,
    "delinquent": false,
    "externalReference": null,
    "additionalEmails": null,
    "metadata": null,
    "updatedAt": "2026-04-01T00:00:00.000Z",
    "createdAt": "2026-04-01T00:00:00.000Z"
  },
  "billing": {
    "frequency": "monthly",
    "frequencyCount": 1,
    "endDate": null,
    "exactDay": null,
    "freeTrialDays": null,
    "autoRenew": true,
    "address": {
      "street": "Avenida Paulista",
      "number": "1000",
      "complement": null,
      "district": "Bela Vista",
      "city": "São Paulo",
      "state": "SP",
      "country": "BR",
      "postcode": "01310100",
      "line": "Avenida Paulista, 1000, Bela Vista, São Paulo - SP, 01310100, BR",
      "fingerprint": null,
      "line1": "Avenida Paulista, 1000",
      "line2": null,
      "line3": "Bela Vista"
    }
  },
  "canceledAt": null,
  "cancellation": null,
  "discount": { "value": 500, "type": "flat", "percentageOfAmount": null },
  "discounts": [
    { "source": "coupon", "couponId": 91, "code": "WELCOME5", "type": "flat", "value": 500, "appliedAmount": 500 }
  ],
  "shippable": false,
  "shipping": null,
  "spplited": false,
  "splits": null,
  "items": [
    {
      "id": "sit_01hqzvabc",
      "name": "Premium Plan",
      "description": null,
      "enabled": true,
      "pricingSchema": "recurring",
      "unitPrice": 9900,
      "quantity": 1,
      "currency": "BRL",
      "images": null,
      "metadata": null,
      "externalReference": null,
      "updatedAt": "2026-04-01T00:00:00.000Z",
      "createdAt": "2026-04-01T00:00:00.000Z"
    }
  ],
  "callback": null,
  "geolocation": null,
  "externalReference": "SUB-1001",
  "metadata": { "source": "checkout" },
  "updatedAt": "2026-04-01T10:15:00.000Z",
  "createdAt": "2026-04-01T00:00:00.000Z",
  "merchant": { "name": "Seller Name", "merchantId": "bus_1234567890", "isSubAccount": false },
  "_links": {
    "self": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc", "method": "GET", "description": "Read a subscription." }
  }
}

Erros comuns

error.codeHTTPQuando
variantNotFound404items[].variantId não existe
variantNotRecurring422A variante não está precificada como recorrente
subscriptionStartDateInPast422billing.startDate anterior a hoje (dia de Brasília); error.params[0] traz { startDate, today }
customerNotFound404customer.id inexistente
cardNotFound404Cartão (payment.card.id) inexistente
addressNotFound404Endereço de cobrança inexistente
couponNotFound404Código de cupom inválido
duplicateSplitRecipient422Dois splits para o mesmo destinatário
splitRecipientNotFound404Destinatário de split inexistente
onBehalfOfInvalid422onBehalfOf não referencia uma sub-conta sua / marketplace não habilitado
fraudBlocked403O antifraude recusou a criação — o mesmo motor da cobrança avulsa, com o contexto desta requisição (IP, cabeçalho X-Device-Fingerprint) e o do comprador (documento, e-mail, cartão). Uma decisão de revisão manual também recusa: a assinatura não fica parada esperando um analista. Nada é criado e nenhum ciclo é cobrado. Os ciclos seguintes não passam de novo pelo antifraude

Catálogo completo: Códigos de Erro.

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