Assinaturas

Criar uma assinatura

POST /v1/subscriptions

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

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": "[email protected]",
      "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" }
  }'

Agenda sob billing. A agenda de cobrança (frequency, frequencyCount, exactDay, startDate, endDate), o freeTrial e o endereço do pagador ficam dentro de billing — espelhando o bloco billing da resposta. O objeto billing é opcional (se omitido, usa frequency=monthly, frequencyCount=1); só o valor nunca vai no request (é derivado do catálogo).

Enviar qualquer um desses campos na raiz (formato antigo) responde 400 dizendo para onde o campo foi. Antes eles eram ignorados em silêncio, e isso cobrava: um freeTrial na raiz não criava período de teste nenhum — a assinatura nascia cobrável e o cartão era cobrado no mesmo dia.

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 (default 1). 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 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)
billing.endDatestringNãoData de término (YYYY-MM-DD)
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
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)

Selectwin-strict. A assinatura não aceita amount, preço manual, nem itens sem variante: o preço é sempre o snapshot da variante (unitPrice/currency/agenda congelados na assinatura). A variante precisa ser recorrente (pricingType = recurring).

Resposta 201 Created

{
  "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]",
    "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,
  "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." }
  }
}

Valores em centavos. items[].unitPrice é inteiro em centavos. O objeto currentCycle reflete o ciclo de cobrança vigente; o detalhe de cada cobrança está nas transações geradas por ciclo. Campos node-only legados (name, card, amount, currentCharge) não fazem parte do objeto; a recorrência fica sob billing.

Erros comuns

error.codeHTTPQuando
variantNotFound404items[].variantId não existe
variantNotRecurring422A variante não está precificada como recorrente
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

Catálogo completo: Códigos de Erro.

How is this guide?

On this page