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": { "id": "cus_abc123" },
"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"
}'Campos principais
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
customer | object | Sim | Cliente por id ou inline (firstName + lastName + email obrigatórios no caminho inline; document/telephone/gender/birthdate/additionalEmails opcionais) |
items[] | array | Sim | 1 a 20 itens, cada um referenciando uma variante recorrente |
items[].variantId | string | Sim | ID da variante (var_...; também aceita o prefixo legado prv_...) |
items[].quantity | integer | Não | Quantidade (default 1). O preço vem da variante |
items[].description | string | Não | Anotação do item (máx. 2048) |
items[].externalReference | string | Não | Sua referência do item |
items[].metadata | object | Não | Metadados do item |
payment.method | enum | Não | credit, pix ou billet (default credit) |
payment.card | object | Sim* | Cartão por id ou inline. *Obrigatório para credit (cobrado automaticamente a cada ciclo) |
payment.installments | integer | Não | Parcelas por cobrança, 1–21 (default 1) |
payment.pix.expiresInMinutes | integer | Não | Expiração do PIX por ciclo (15–525600) |
payment.billet.expiresInDays | integer | Não | Expiração do boleto por ciclo (1–365) |
billing.frequency | enum | Não | daily, weekly, monthly, yearly (default monthly) |
billing.frequencyCount | integer | Não | Multiplicador da frequência, 1–365 (default 1). Ex.: billing.frequency=monthly + billing.frequencyCount=3 = a cada 3 meses |
billing.exactDay | integer | Não | Dia fixo do mês para a cobrança (1–31) |
billing.startDate | string | Não | Data de início (YYYY-MM-DD; default: hoje) |
billing.endDate | string | Não | Data de término (YYYY-MM-DD) |
billing.freeTrial | object | Não | Período de teste: { "enabled": true, "days": 7 } |
billing.address | object | Não* | Endereço de cobrança (id ou inline). *Obrigatório para billet |
autoRenew | boolean | Não | Renovação automática (default true) |
discounts | array | Não | Cupons 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) |
splits[] | array | Não | Divisão de receita por ciclo: { recipient, type, value } (máx. 20) — veja Splits |
name | string | Não | Nome de exibição da assinatura |
description | string | Não | Descrição livre (aceita, mas não persistida na leitura) |
externalReference | string | Não | Sua referência externa |
metadata | object | Não | Pares chave-valor livres |
shipping | object | Não | Dados de entrega (assinaturas com produto físico) |
callback.webhookUrl | string (url) | Não | Webhook específico desta assinatura (callback.active default true) |
onBehalfOf | string | Não | publicId de uma sub-conta sua: cria a assinatura na sub-conta e cobra a taxa de aplicação da plataforma a cada ciclo (marketplace) |
📌 Agenda sob
billing. A agenda (frequency,frequencyCount,exactDay,startDate,endDate), ofreeTriale o endereço ficam sobbilling— espelhando a resposta. Enviar esses campos na raiz (formato antigo) faz com que sejam ignorados silenciosamente. O valor nunca vai no request (é derivado do catálogo).
⛔ 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,
"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"
}
},
"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 objetocurrentCyclereflete 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 sobbilling.
Erros comuns
error.code | HTTP | Quando |
|---|---|---|
variantNotFound | 404 | items[].variantId não existe |
variantNotRecurring | 422 | A variante não está precificada como recorrente |
customerNotFound | 404 | customer.id inexistente |
cardNotFound | 404 | Cartão (payment.card.id) inexistente |
addressNotFound | 404 | Endereço de cobrança inexistente |
couponNotFound | 404 | Código de cupom inválido |
duplicateSplitRecipient | 422 | Dois splits para o mesmo destinatário |
splitRecipientNotFound | 404 | Destinatário de split inexistente |
onBehalfOfInvalid | 422 | onBehalfOf não referencia uma sub-conta sua / marketplace não habilitado |
Catálogo completo: Códigos de Erro.
How is this guide?