Visão geral
O recurso Produtos (Products) é o seu catálogo na Selectwin. Cada produto agrupa uma ou mais Variantes (Variants), e é a variante que carrega o preço e as regras de cobrança — é ela que você referenci
O recurso Produtos (Products) é o seu catálogo na Selectwin. Cada produto agrupa uma ou mais Variantes (Variants), e é a variante que carrega o preço e as regras de cobrança — é ela que você referencia ao criar transações e assinaturas. Use esta página como ponto de partida: ela explica o modelo do objeto, o ciclo de vida e todas as operações disponíveis.
O que é (e por que existe)
Pense em um produto como a "ficha" do que você vende (nome, descrição, imagens, garantia), e nas variantes como as ofertas concretas desse produto, cada uma com seu preço. Um produto "Plano Premium" pode ter as variantes "Mensal", "Anual" e "Vitalício" — mesmo produto, preços e cadências diferentes.
A separação importa porque o produto nunca tem preço; quem tem preço é a variante (no objeto pricing). Isso permite vender o mesmo produto de várias formas sem duplicar o cadastro.
- Uma variante de cobrança única (
pricing.type = oneTime) é o que você cobra em uma Transação avulsa. - Uma variante recorrente (
pricing.type = recurring) é o que compõe os itens de uma Assinatura.
Nota
Todo produto pertence à conta autenticada pela SelectKey. As respostas de produto não incluem o objeto merchant. Para as regras gerais (autenticação, dinheiro em centavos, datas em UTC, IDs opacos), veja Convenções.
Modelo do objeto Produto
Identificadores: produto usa o prefixo prd_ e variante usa var_. Trate-os como strings opacas — não faça parsing. Valores monetários (unitPrice, oldPrice, costPerItem) são inteiros em centavos (9900 = R$ 99,00) e datas são ISO 8601 em UTC.
{
"id": "prd_01hqzvabc",
"enabled": true,
"name": "Plano Premium",
"description": "Full access plan",
"type": "digital", // enum: physical | digital | other
"language": "pt-BR",
"category": "saas",
"slug": "plano-premium",
"images": ["https://cdn.selectwin.io/p/img1.png"],
"warrantyDays": 30, // dias de garantia (7..3650)
"externalReference": "PROD-EXT-1", // sua referência no seu sistema
"variants": [ /* ver modelo da variante abaixo */ ],
"createdAt": "2026-04-12T17:56:33.000Z",
"updatedAt": "2026-04-12T17:56:33.000Z"
}Campos do produto
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Identificador público (prd_...), opaco |
name | string | Nome do produto |
slug | string | Identificador legível para URLs |
type | string | physical | digital | other |
language | string | Código de idioma (ex.: pt-BR) |
category | string | Categoria de negócio |
salesPage | string (url) | Página de vendas |
images | array | URLs de imagens |
warrantyDays | integer | Dias de garantia (faixa 7..3650) |
salesQty | integer | Quantidade vendida (somente leitura; aparece em listagens) |
enabled | boolean | Se o produto está ativo/vendável |
externalReference | string | Sua referência externa de catálogo |
variants | array | Variantes do produto, cada uma com pricing |
createdAt / updatedAt | string (date-time) | Carimbos ISO 8601 UTC |
Em listagens (
GET /v1/products), os itens são projeções leves: trazem campos comoid,name,slug,category,salesQty,enabled,images,typee os timestamps — mas não trazemvariants. Para o produto completo com variantes, use Consultar produto.
Modelo do objeto Variante
A variante é onde mora o preço. Modelo completo (como retornado em Consultar variante):
{
"id": "var_01hqzvabc",
"productId": "prd_01hqzvabc",
"name": "Mensal",
"enabled": true,
"description": "Monthly billing",
"sku": "SKU-M",
"pricing": {
"unitPrice": 9900, // centavos (500..200000000)
"currency": "BRL", // ISO 4217; hoje só BRL
"schema": "unit", // como o preço é calculado (só "unit")
"type": "recurring", // oneTime | recurring
"oldPrice": 14900, // preço "de" (riscado), centavos
"costPerItem": 5000, // custo (COGS), centavos — para margem
"billingType": "prepaid", // prepaid | postpaid | exactday
"billingFrequency": "monthly",// daily | weekly | monthly | yearly
"billingFrequencyCount": 1, // multiplicador da frequência
"billingExactDay": 10, // dia do mês quando billingType=exactday
"cycles": 12, // nº de ciclos (null = infinito)
"trialInterval": "day", // day | week | month | year
"trialIntervalCount": 7, // duração do trial
"daysTrial": 7 // trial em dias (derivado, leitura)
},
"images": ["https://cdn.selectwin.io/v/var.png"],
"metadata": { "tier": "pro" },
"attributes": {},
"externalReference": "VAR-EXT-1",
"createdAt": "2026-04-12T17:56:33.000Z",
"updatedAt": "2026-04-12T17:56:33.000Z"
}Campos de pricing
| Campo | Aplica a | Tipo / enum | Descrição |
|---|---|---|---|
unitPrice | ambos | integer, 500..200000000 | Preço unitário em centavos (obrigatório) |
currency | ambos | enum ["BRL"] | ISO 4217 (obrigatório) |
schema | ambos | enum ["unit"] | Como o preço é calculado. Hoje só unit. Imutável |
type | ambos | enum ["oneTime","recurring"] | Natureza da cobrança. Default oneTime. Imutável |
oldPrice | ambos | integer, 500..200000000 | Preço "de" (riscado/promocional), em centavos |
costPerItem | ambos | integer, 0..200000000 | Custo do item (COGS) em centavos, base para margem no analytics. Pode ser 0 |
billingType | recurring | enum ["prepaid","postpaid","exactday"] | Tipo de cobrança recorrente. Obrigatório quando type=recurring |
billingFrequency | recurring | enum ["daily","weekly","monthly","yearly"] | Unidade da cadência. Obrigatório quando type=recurring |
billingFrequencyCount | recurring | integer, 1..999 | Multiplicador da frequência (ex.: monthly + 3 = trimestral). Obrigatório quando type=recurring |
billingExactDay | recurring | integer, 1..31 | Dia fixo de cobrança, usado quando billingType=exactday |
cycles | recurring | integer, 1..999 | Total de ciclos. Omitir/null = infinito |
trialInterval | recurring | enum ["day","week","month","year"] | Unidade do período de teste |
trialIntervalCount | recurring | integer, 1..365 | Duração do trial (ex.: 2 + week = 2 semanas) |
O trial é bidimensional: combine
trialInterval(unidade) comtrialIntervalCount(quantidade). O campodaysTrialaparece apenas na leitura como a duração equivalente em dias — não o envie ao criar/atualizar.
Modelo de precificação (dois eixos)
A precificação é organizada em dois eixos independentes, ambos imutáveis depois de criados.
Eixo 1 — pricing.type (natureza da cobrança)
pricing.type | Significado | Onde é usada |
|---|---|---|
oneTime | Cobrança única (default) | Transações |
recurring | Cobrança recorrente | Assinaturas |
- Uma variante
recurringnão pode ser cobrada em transação avulsa →variantRecurringNotAllowedInTransaction(422). - Uma variante
oneTimenão pode entrar em assinatura →oneTimeVariantNotAllowedInSubscription(422). - Tentar mudar o
typeapós a criação →pricingTypeImmutable(422).
Eixo 2 — pricing.schema (como o preço é calculado)
pricing.schema | Significado |
|---|---|
unit | Preço por unidade (unitPrice × quantity) |
Hoje só existe
unit. Tentar mudar oschemaapós a criação →pricingSchemaImmutable(422).
Ciclo de vida
Um produto e suas variantes são criados juntos, vivem sendo editados (com a ressalva dos campos imutáveis de preço) e podem ser desativados (enabled: false) ou removidos. Desativar é reversível e tira a oferta de circulação sem apagar histórico; excluir é uma ação destrutiva.
Atenção
enabled = false é o caminho reversível para tirar um produto ou variante de venda. DELETE remove o recurso do catálogo — confirme antes que nenhuma assinatura, link de pagamento ou cupom dependa daquela variante.
Operações disponíveis
Produtos
| Operação | Método e caminho | Página |
|---|---|---|
| Criar produto (com variantes inline) | POST /v1/products | Criar |
| Listar produtos (paginado) | GET /v1/products | Listar |
| Listar todos (sem paginação leve) | GET /v1/products/listall | Listar |
| Consultar produto + variantes | GET /v1/products/{productId} | Consultar |
| Substituir produto (completo) | PUT /v1/products/{productId} | Atualizar |
| Atualizar parcialmente | PATCH /v1/products/{productId} | Atualizar |
| Excluir produto | DELETE /v1/products/{productId} | Atualizar |
Variantes
| Operação | Método e caminho | Página |
|---|---|---|
| Listar variantes de um produto | GET /v1/products/{productId}/variants | Variantes |
| Adicionar variante a um produto | POST /v1/products/{productId}/variants | Variantes |
Atualizar variante (por id no corpo) | PATCH /v1/products/{productId}/variants | Variantes |
| Listar todas as variantes do produto | GET /v1/products/variants/listall | Variantes |
| Listar todas as variantes (conta) | GET /v1/variants | Variantes |
| Consultar variante por ID | GET /v1/variants/{variantId} | Variantes |
| Excluir variante | DELETE /v1/variants/{variantId} | Variantes |
Há dois "endereços" para variantes: aninhado no produto (
/v1/products/{productId}/variants) e no nível da conta (/v1/variantse/v1/variants/{variantId}). A leitura individual e a exclusão usam o caminho de conta com ovariantId; a criação e a atualização em lote usam o caminho aninhado no produto.
Exemplo rápido
Criar um produto digital já com uma variante mensal recorrente. Todas as requisições usam o header SelectKey (em produção começa com sl_live_; em sandbox, sl_test_) — nunca Authorization: Bearer/Basic.
curl -X POST https://api.selectwin.io/v1/products \
-H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: prod-create-2026-06-10-001" \
-d '{
"name": "Plano Premium",
"type": "digital",
"category": "saas",
"warrantyDays": 30,
"variants": [
{
"name": "Mensal",
"sku": "SKU-M",
"pricing": {
"unitPrice": 9900,
"currency": "BRL",
"type": "recurring",
"billingType": "prepaid",
"billingFrequency": "monthly",
"billingFrequencyCount": 1
}
}
]
}'Campos obrigatórios no produto: name, type, category, warrantyDays e ao menos uma variant. Em cada variante, name e pricing são obrigatórios; dentro de pricing, unitPrice e currency sempre, e os campos de billing* quando type=recurring. Detalhes e variações em Criar produto.
Erros específicos do recurso
Trate sempre pelo error.code (estável), não pela message. Os códigos abaixo são os específicos de Produtos & Variantes; os transversais (401 unauthorized, 403 forbidden, 422 unprocessableEntity, 429 tooManyRequests, 500 serverError) também se aplicam.
error.code | HTTP | Quando ocorre |
|---|---|---|
productIdNotFound | 404 | Produto não encontrado |
productIdIsInvalid | 400 | ID de produto inválido ou inexistente |
variantIdNotFound | 404 | Variante não encontrada |
variantIdIsInvalid / productVariantIdIsInvalid | 400 | ID de variante inválido ou inexistente |
productVariantIdIsRequired | 400 | ID da variante é obrigatório (ex.: PATCH de variante sem id) |
pricingTypeImmutable | 422 | Tentou alterar pricing.type após a criação |
pricingSchemaImmutable | 422 | Tentou alterar pricing.schema após a criação |
variantRecurringNotAllowedInTransaction | 422 | Variante recurring usada em transação avulsa |
productCreationFailed / productDeleteFailed | 422 | Falha ao criar / excluir o produto |
productCreateLimitReached | 403 | Limite de criação de produtos atingido |
Catálogo completo e estrutura do envelope: Códigos de Erro e Tratamento de Erros.
Boas práticas
- Decida o
pricing.typee oschemaantes de criar — eles são imutáveis. Para "trocar de preço", crie uma nova variante e desative a antiga, em vez de tentar editar o tipo. - Use
externalReferenceno produto e na variante para casar com oiddo seu próprio catálogo; assim você relaciona seus registros sem depender de parsing de IDs. - Modele o trial nos dois campos (
trialInterval+trialIntervalCount). Não tente enviardaysTrial— ele é apenas leitura. - Desative em vez de excluir quando quiser pausar vendas mantendo histórico e vínculos (
enabled: false). ReserveDELETEpara limpeza definitiva. - Preencha
costPerItemse quiser relatórios de margem/lucro corretos no analytics; pode ser0, mas omiti-lo zera a análise de COGS daquela variante. - Envie
X-Idempotency-Keyem criações e atualizações para que uma repetição (timeout, retry) não gere produtos ou variantes duplicados — veja Idempotência. - Para o objeto completo, consulte o recurso individual. As listagens são projeções leves e não trazem
variants(no produto) nem todos os campos depricing.
Veja também
- Criar produto — payload completo com variantes inline
- Consultar produto — produto + variantes pelo
productId - Listar produtos — paginação e filtros
- Atualizar / Excluir —
PUT,PATCHeDELETE - Variantes — criar, atualizar, ler e excluir variantes
- Transações e Assinaturas — onde as variantes são cobradas
- Convenções · Idempotência · Paginação · Códigos de Erro
How is this guide?