SelectwinDOCS
Assinaturas

Itens da assinatura

Os itens são as linhas que compõem o que uma assinatura cobra a cada ciclo: cada item referencia um produto (em geral uma variante recorrente, var...), com uma quantidade e um preço unitário. Use este

Os itens são as linhas que compõem o que uma assinatura cobra a cada ciclo: cada item referencia um produto (em geral uma variante recorrente, var_...), com uma quantidade e um preço unitário. Use estes endpoints para adicionar, listar, consultar, atualizar e remover itens de uma assinatura já existente — por exemplo, para vender um upsell, um add-on ou ajustar quantidades sem recriar a assinatura.

Para criar a assinatura inteira de uma vez (cliente, plano e itens iniciais), use Create. Esta página cobre alterações após a assinatura existir.

Como funciona

Cada assinatura mantém uma coleção de itens em items[]. Um item tem um id próprio (item_..., opaco — não faça parsing), um name, um unitPrice (inteiro em centavos), uma quantity e um pricingSchema que indica como o preço se aplica (ex.: recurring, unit). O valor cobrado em cada ciclo deriva da soma dos itens habilitados (enabled: true).

dois modos de informar um item ao adicioná-lo ou atualizá-lo:

  • Modo catálogo (recomendado): você envia id apontando para uma variante recorrente do seu catálogo (var_...). O preço, a moeda e a agenda de cobrança vêm da variante; você controla quantidade e metadados. Este é o modo coerente com o modelo Stripe-strict do recurso (veja a Visão Geral).
  • Modo manual: você envia o objeto pricing com unitPrice, quantity e currency diretamente, sem id. Útil para linhas avulsas quando sua conta permite.

Stripe-strict na criação

O endpoint de criação da assinatura (POST /v1/subscriptions) rejeita itens manuais (manualItemNotAllowedInSubscription) — lá todo item precisa de id de variante. As regras de itens manuais nos endpoints de add/update abaixo dependem da configuração da sua conta; em caso de dúvida, prefira o modo catálogo. Detalhes do modelo em Visão Geral.

Estas operações são síncronas: a resposta já reflete o estado novo. Mudanças no conjunto de itens afetam o valor dos próximos ciclos; o ciclo atual já faturado não é refeito retroativamente. Acompanhe mudanças de cobrança pelos webhooks da assinatura, nunca por polling — veja Proibição de Polling.

Operações

OperaçãoMétodo e caminhoRetorna
Adicionar itemPOST /v1/subscriptions/{subscriptionId}/itemsa assinatura completa atualizada
Listar itensGET /v1/subscriptions/{subscriptionId}/itemslista paginada de itens (projeção leve)
Consultar itemGET /v1/subscriptions/{subscriptionId}/items/{itemId}o item
Atualizar itemPUT /v1/subscriptions/{subscriptionId}/items/{itemId}o item atualizado
Remover itemDELETE /v1/subscriptions/{subscriptionId}/items?itemId={itemId}a assinatura completa atualizada

Atenção: dois jeitos de identificar o item ao remover

Para remover, o itemId vai na query string (?itemId=item_...), não no caminho. Já para consultar e atualizar, o itemId vai no caminho (/items/{itemId}). São formatos diferentes — preste atenção.

Convenções

Todas as requisições usam o header SelectKey (nunca Authorization: Bearer/Basic), dinheiro em centavos, datas em ISO 8601 UTC e campos em camelCase. Resumo em Convenções; autenticação em Autenticação. Base URL: https://api.selectwin.io/v1.


Adicionar item

POST /v1/subscriptions/{subscriptionId}/items

Inclui um novo item (upsell, add-on) na assinatura. A resposta 200 retorna a assinatura completa já com o item presente em items[].

Headers

CabeçalhoValor
SelectKeysl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ (produção) — em sandbox a chave começa com sl_test_
Content-Typeapplication/json
X-Idempotency-KeyRecomendado — evita adicionar o item duas vezes se a chamada for repetida (Idempotência)

Parâmetros de caminho

NomeTipoObrigatórioDescrição
subscriptionIdstringSimID da assinatura (subs_...)

Corpo

Nenhum campo é individualmente obrigatório no esquema, mas na prática você informa ou id (modo catálogo) ou o objeto pricing completo (modo manual).

CampoTipoObrigatórioDescrição
idstring (var_...)NãoID da variante (modo catálogo). Padrão ^[a-z]+_[A-Za-z0-9]+$
pricingobjectNãoPreço da linha (modo manual)
pricing.unitPriceintegerNãoPreço unitário em centavos (1 a 20000000)
pricing.quantityintegerNãoQuantidade (1 a 999999)
pricing.currencystringNãoMoeda — enum ["BRL"]
namestringNãoNome de exibição
descriptionstringNãoDescrição da linha
enabledbooleanNãoSe o item está ativo na assinatura
externalReferencestringNãoSua referência externa para a linha
metadataobjectNãoPares chave-valor (metadados da linha)
curl -X POST "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items" \
  -H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: add-item-7f1c2a" \
  -d '{
    "pricing": { "unitPrice": 4900, "quantity": 1, "currency": "BRL" },
    "id": "var_abc123",
    "name": "Plano Premium",
    "description": "Plano mensal",
    "enabled": true,
    "externalReference": "line-1",
    "metadata": { "sku": "SKU-1" }
  }'

Variação modo catálogo (deixa preço/moeda virem da variante):

curl -X POST "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items" \
  -H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ" \
  -H "Content-Type: application/json" \
  -d '{ "id": "var_abc123", "pricing": { "quantity": 2 } }'

Resposta 200

Retorna a assinatura inteira (mesmo formato de Read). Em items[], cada item traz id, quantity, unitPrice, pricingSchema, name, description, enabled, currency, metadata, images, externalReference, updatedAt, createdAt.

{
  "id": "subs_01hqzvabc",
  "status": "active",
  "currency": "BRL",
  "method": "credit",
  "type": "prepaid",
  "items": [
    {
      "id": "item_01hqzvabc",
      "quantity": 1,
      "unitPrice": 9900,
      "pricingSchema": "unit",
      "name": "Premium Plan",
      "description": "Plano Premium mensal",
      "enabled": true,
      "currency": "BRL",
      "metadata": null,
      "images": ["https://cdn.example.com/product.png"],
      "externalReference": null,
      "updatedAt": "2026-04-12T17:56:33.000Z",
      "createdAt": "2026-04-12T17:56:33.000Z"
    }
  ],
  "updatedAt": "2026-04-12T17:56:33.000Z",
  "createdAt": "2026-04-12T17:56:33.000Z",
  "merchant": { "name": "Seller Name", "merchantId": "bus_1234567890", "isSubAccount": false },
  "_links": {
    "self": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items", "method": "POST", "description": "Add item of subscription." },
    "list": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items", "method": "GET", "description": "List items of a subscription." }
  }
}

Listar itens

GET /v1/subscriptions/{subscriptionId}/items

Devolve os itens da assinatura em formato paginado. Os itens da lista são uma projeção leve — campos como merchant por item não aparecem; para o objeto individual completo, use a consulta por itemId.

Parâmetros

NomeEmTipoObrigatórioDescrição
subscriptionIdcaminhostringSimID da assinatura (subs_...)
limitquerynumberNãoItens por página (1 a 100; ex.: 20)
offsetquerynumberNãoQuantos itens pular (≥ 0)
sortquerystringNãoOrdem: enum ["ascending","descending"]

Sobre paginação (page, offset, hasMore), veja Paginação.

curl "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items?limit=20&offset=0" \
  -H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ"

Resposta 200

{
  "offset": 0, "limit": 20, "total": 1, "hasMore": false,
  "page": { "current": 1, "total": 1, "offset": { "first": 0, "prev": null, "next": null, "last": 0 } },
  "data": [
    {
      "id": "item_01hqzvabc",
      "name": "Premium Plan",
      "description": "Monthly access",
      "enabled": true,
      "pricingSchema": "recurring",
      "unitPrice": 9900,
      "quantity": 1,
      "currency": "BRL",
      "images": [],
      "metadata": {},
      "externalReference": "var-premium",
      "updatedAt": "2026-04-12T17:56:33.000Z",
      "createdAt": "2026-04-12T17:56:33.000Z"
    }
  ],
  "merchant": { "name": "Seller Name", "merchantId": "bus_1234567890", "isSubAccount": false },
  "_links": { "self": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items", "method": "GET" } }
}

Consultar item

GET /v1/subscriptions/{subscriptionId}/items/{itemId}

Retorna um item individual com todos os campos, incluindo o bloco merchant.

Parâmetros de caminho

NomeTipoObrigatórioDescrição
subscriptionIdstringSimID da assinatura (subs_...)
itemIdstringSimID do item (item_...)
curl "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items/item_01hqzvabc" \
  -H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ"

Resposta 200

{
  "id": "item_01hqzvabc",
  "name": "Premium Plan",
  "description": "Monthly access",
  "enabled": true,
  "pricingSchema": "recurring",
  "unitPrice": 9900,
  "quantity": 1,
  "currency": "BRL",
  "images": [],
  "metadata": {},
  "externalReference": "var-premium",
  "updatedAt": "2026-04-12T17:56:33.000Z",
  "createdAt": "2026-04-12T17:56:33.000Z",
  "merchant": { "name": "Seller Name", "merchantId": "bus_1234567890", "isSubAccount": false },
  "_links": { "self": { "href": "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items/item_01hqzvabc", "method": "GET" } }
}
CampoTipoDescrição
idstringID do item (item_...)
namestringNome de exibição
descriptionstringDescrição
enabledbooleanSe conta para a cobrança do ciclo
pricingSchemastringComo o preço se aplica (ex.: recurring, unit)
unitPriceintegerPreço unitário em centavos
quantityintegerQuantidade
currencystringMoeda (BRL)
imagesarrayURLs de imagem
metadataobjectMetadados da linha
externalReferencestringSua referência externa
createdAt / updatedAtstringTimestamps ISO 8601 UTC

Atualizar item

PUT /v1/subscriptions/{subscriptionId}/items/{itemId}

Substitui os dados do item (quantidade, preço, nome, metadados…). Aceita os mesmos campos do corpo de Adicionar item. Retorna o objeto do item atualizado (não a assinatura inteira).

Parâmetros de caminho

NomeTipoObrigatórioDescrição
subscriptionIdstringSimID da assinatura (subs_...)
itemIdstringSimID do item (item_...)

Corpo

Mesma tabela de campos do Adicionar item: id, pricing.unitPrice, pricing.quantity, pricing.currency, name, description, enabled, externalReference, metadata. No modo catálogo, o preço e a moeda continuam derivando da variante — você ajusta principalmente quantity, enabled e metadados.

curl -X PUT "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items/item_01hqzvabc" \
  -H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ" \
  -H "Content-Type: application/json" \
  -d '{
    "pricing": { "quantity": 2, "unitPrice": 4900, "currency": "BRL" },
    "enabled": true,
    "metadata": { "sku": "SKU-1" }
  }'

A resposta 200 tem o mesmo formato da seção Consultar item, com updatedAt refletindo a alteração.


Remover item

DELETE /v1/subscriptions/{subscriptionId}/items?itemId={itemId}

Remove um item da assinatura. O itemId vai na query string (obrigatório). Retorna a assinatura completa atualizada, já sem o item removido em items[].

Parâmetros

NomeEmTipoObrigatórioDescrição
subscriptionIdcaminhostringSimID da assinatura (subs_...)
itemIdquerystringSimID do item a remover (item_...). Padrão ^[a-z]+_[A-Za-z0-9]+$
curl -X DELETE "https://api.selectwin.io/v1/subscriptions/subs_01hqzvabc/items?itemId=item_01hqzvabc" \
  -H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ"

A resposta 200 é a assinatura completa (formato de Read), com items[] já sem o item removido.

Não esvazie a assinatura sem querer

Remover o último item ativo deixa a assinatura sem o que cobrar. Se o objetivo é apenas suspender a cobrança de uma linha, prefira atualizar o item com enabled: false em vez de removê-lo — assim você preserva o histórico e pode reativá-lo depois.


Erros

A API sinaliza falhas pelo error.code (estável), não pela message. Veja o envelope em Tratamento de Erros e a lista completa em Códigos de Erro.

error.codeHTTPQuando ocorre
invalidParameters400Corpo/parâmetros inválidos (ver error.params) — ex.: quantity fora de 1–999999, unitPrice fora de 1–20000000
variantIdIsInvalid / productVariantIdIsInvalid400O id informado não é uma variante válida
variantIdNotFound404Variante referenciada não existe
manualItemNotAllowedInSubscription422Item manual (sem id de variante) não permitido nesta assinatura
oneTimeVariantNotAllowedInSubscription422Variante não recorrente (oneTime) não pode ser usada
variantScheduleDivergent422A variante tem agenda de cobrança divergente das demais
unauthorized401SelectKey ausente, inválida ou revogada
forbidden403Autenticado, mas sem permissão para esta assinatura
notFound404Assinatura (subscriptionId) ou item (itemId) não encontrado
unprocessableEntity422Regra de negócio impede a operação
tooManyRequests429Limite de requisições excedido (respeite error.retryAfterMinutes)
serverError500Erro interno — repita com backoff

O add/update/remove também pode retornar 402 insufficientFundsError em cenários que disparam cobrança imediata associada à mudança do item.

Boas práticas

  • Prefira o modo catálogo (id de variante) sempre que possível: o preço, a moeda e a agenda vêm da variante e ficam consistentes com o modelo do recurso. Reserve pricing.unitPrice/currency para casos manuais realmente necessários.
  • Use enabled: false em vez de remover quando a pausa for temporária — preserva o item e seu histórico.
  • Envie X-Idempotency-Key em POST .../items para não duplicar add-ons se a chamada for reenviada após um timeout de rede.
  • Cuidado com os dois formatos de itemId: caminho para consultar/atualizar; query string para remover.
  • Dinheiro sempre em centavos (4900 = R$ 49,00) e moeda BRL. Nunca envie ponto flutuante.
  • Correlacione com externalReference/metadata para casar a linha com o seu catálogo ou pedido interno.
  • Não faça polling para detectar o recálculo do próximo ciclo — reaja aos webhooks da assinatura (Proibição de Polling).
  • Trate IDs como opacos: armazene item_... e var_... como strings inteiras, sem parsing.

Veja também

How is this guide?

On this page