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).
Há dois modos de informar um item ao adicioná-lo ou atualizá-lo:
- Modo catálogo (recomendado): você envia
idapontando 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
pricingcomunitPrice,quantityecurrencydiretamente, semid. Ú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ção | Método e caminho | Retorna |
|---|---|---|
| Adicionar item | POST /v1/subscriptions/{subscriptionId}/items | a assinatura completa atualizada |
| Listar itens | GET /v1/subscriptions/{subscriptionId}/items | lista paginada de itens (projeção leve) |
| Consultar item | GET /v1/subscriptions/{subscriptionId}/items/{itemId} | o item |
| Atualizar item | PUT /v1/subscriptions/{subscriptionId}/items/{itemId} | o item atualizado |
| Remover item | DELETE /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çalho | Valor |
|---|---|
SelectKey | sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ (produção) — em sandbox a chave começa com sl_test_ |
Content-Type | application/json |
X-Idempotency-Key | Recomendado — evita adicionar o item duas vezes se a chamada for repetida (Idempotência) |
Parâmetros de caminho
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
subscriptionId | string | Sim | ID 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).
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string (var_...) | Não | ID da variante (modo catálogo). Padrão ^[a-z]+_[A-Za-z0-9]+$ |
pricing | object | Não | Preço da linha (modo manual) |
pricing.unitPrice | integer | Não | Preço unitário em centavos (1 a 20000000) |
pricing.quantity | integer | Não | Quantidade (1 a 999999) |
pricing.currency | string | Não | Moeda — enum ["BRL"] |
name | string | Não | Nome de exibição |
description | string | Não | Descrição da linha |
enabled | boolean | Não | Se o item está ativo na assinatura |
externalReference | string | Não | Sua referência externa para a linha |
metadata | object | Não | Pares 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
| Nome | Em | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
subscriptionId | caminho | string | Sim | ID da assinatura (subs_...) |
limit | query | number | Não | Itens por página (1 a 100; ex.: 20) |
offset | query | number | Não | Quantos itens pular (≥ 0) |
sort | query | string | Não | Ordem: 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
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
subscriptionId | string | Sim | ID da assinatura (subs_...) |
itemId | string | Sim | ID 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" } }
}| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID do item (item_...) |
name | string | Nome de exibição |
description | string | Descrição |
enabled | boolean | Se conta para a cobrança do ciclo |
pricingSchema | string | Como o preço se aplica (ex.: recurring, unit) |
unitPrice | integer | Preço unitário em centavos |
quantity | integer | Quantidade |
currency | string | Moeda (BRL) |
images | array | URLs de imagem |
metadata | object | Metadados da linha |
externalReference | string | Sua referência externa |
createdAt / updatedAt | string | Timestamps 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
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
subscriptionId | string | Sim | ID da assinatura (subs_...) |
itemId | string | Sim | ID 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
| Nome | Em | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
subscriptionId | caminho | string | Sim | ID da assinatura (subs_...) |
itemId | query | string | Sim | ID 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.code | HTTP | Quando ocorre |
|---|---|---|
invalidParameters | 400 | Corpo/parâmetros inválidos (ver error.params) — ex.: quantity fora de 1–999999, unitPrice fora de 1–20000000 |
variantIdIsInvalid / productVariantIdIsInvalid | 400 | O id informado não é uma variante válida |
variantIdNotFound | 404 | Variante referenciada não existe |
manualItemNotAllowedInSubscription | 422 | Item manual (sem id de variante) não permitido nesta assinatura |
oneTimeVariantNotAllowedInSubscription | 422 | Variante não recorrente (oneTime) não pode ser usada |
variantScheduleDivergent | 422 | A variante tem agenda de cobrança divergente das demais |
unauthorized | 401 | SelectKey ausente, inválida ou revogada |
forbidden | 403 | Autenticado, mas sem permissão para esta assinatura |
notFound | 404 | Assinatura (subscriptionId) ou item (itemId) não encontrado |
unprocessableEntity | 422 | Regra de negócio impede a operação |
tooManyRequests | 429 | Limite de requisições excedido (respeite error.retryAfterMinutes) |
serverError | 500 | Erro interno — repita com backoff |
O
add/update/removetambém pode retornar402 insufficientFundsErrorem cenários que disparam cobrança imediata associada à mudança do item.
Boas práticas
- Prefira o modo catálogo (
idde 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. Reservepricing.unitPrice/currencypara casos manuais realmente necessários. - Use
enabled: falseem vez de remover quando a pausa for temporária — preserva o item e seu histórico. - Envie
X-Idempotency-KeyemPOST .../itemspara 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 moedaBRL. Nunca envie ponto flutuante. - Correlacione com
externalReference/metadatapara 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_...evar_...como strings inteiras, sem parsing.
Veja também
- Visão Geral — o objeto Assinatura, o modelo Stripe-strict e o ciclo de vida.
- Create — criar a assinatura com seus itens iniciais.
- Read — formato completo da assinatura (retornado por add/remove).
- List — listar assinaturas.
- Cycles — ciclos de cobrança e renovação.
- Splits — divisão de receita da assinatura.
- Cancel — cancelar a assinatura.
- Convenções · Códigos de Erro · Paginação · Idempotência
How is this guide?