Visão geral
Este guia cobre o cadastro base do produto: nome, SKU, unidade, dimensões e fotos.
| Tema | Guia |
|---|---|
Tabela de preços (default / wholesale) | Produtos: preços |
| Movimentação e saldo de estoque | Produtos: estoque |
| Medidas por faixa de quantidade (embalagem fechada) | Produtos: medidas |
Conceitos
Unidade de medida (base_unit):un, pc, cx, pct, kg, lt, mt, m2, m3.
Tipo de preço (price_type):default (valor único) ou wholesale (até 5 faixas progressivas por quantidade). Detalhes em Preços.
Disponibilidade:is_available_for_sale controla a visibilidade do produto no catálogo. is_industrializable indica produto fabricado sob demanda.
Dimensões (opcionais no cadastro, necessárias para o frete):dimensions.height, dimensions.width, dimensions.length (cm) e dimensions.weight (kg) descrevem a unidade (min_quantity = 1). Podem ficar de fora do POST/PUT /api/products, mas sem elas o produto não é cotado no frete até serem preenchidas. Quando informadas, cada valor precisa ser no mínimo 0.001.
Essas medidas cobrem só a venda unitária. Embalagens fechadas (caixa, fardo, pallet) do atacado têm medidas próprias por faixa de quantidade, gerenciadas em rota separada (ver Produtos: medidas).
Empacotamento (cubagem de frete):keep_flat trava a rotação no eixo vertical: o item viaja deitado/plano e não pode ser girado em pé ao montar o volume. ship_isolated faz o SKU sair em volume próprio, nunca dividindo a mesma caixa com outro item. Ambos são opcionais (default false) e graváveis no POST/PUT.
Dimensões formatadas (dimensions_formatted): ao chamar com ?include_dimensions_formatted=true, a resposta inclui um objeto extra com as medidas prontas para exibição (melhor unidade, padrão pt-BR; ex.: "1,58 m", "25,00 cm", "500g"). Sem a query, o campo não vem.
O objeto que GET /products/{id} devolve (produto, preços e estoque juntos):
{
"product": {
"id": "01H8X…", // ID do produto
"name": "Produto Exemplo A",
"sku": "SKU-001", // único por loja
"base_unit": "un", // ← Unidade de medida
"price_type": "default", // ← Tipo de preço (default | wholesale)
"dimensions": {…}, // ← Dimensões (cm) + peso (kg)
"is_available_for_sale": true, // ← Disponibilidade no catálogo
"is_industrializable": false, // fabricado sob demanda
"auto_wholesale_pricing": false, // atacado por % de desconto (ver Preços)
"allow_sale_without_stock": false, // venda sem estoque (sob encomenda)
"advanced_pricing": false, // liga o preço unitário com 3 casas decimais
"price_scale": 2, // somente leitura: 2 ou 3 casas no unitário
"min_purchase_quantity": 1, // piso de compra, em unidades físicas
"allow_fractional_quantity": false, // false = múltiplos exatos do mínimo
"keep_flat": false, // empacotamento: manter deitado (trava rotação vertical)
"ship_isolated": false, // empacotamento: enviar em volume próprio
"quantity": 100, // estoque físico
"reserved_quantity": 5, // reservado em pedidos abertos
"available_quantity": 95, // disponível p/ venda
"thumbnail": { // imagem principal
"id": "01JMZ…", // ID da imagem
"resources": [{…}] // variações (name, size, url)
},
"price": 50.0 // default → preço-base; wholesale → "min_price" + "max_price"
},
"prices": [{…}], // faixas de preço (ver Preços)
"stock": [{…}] // saldo por local (ver Estoque)
}Produto
Na criação, name, sku, base_unit e price_type são obrigatórios; o resto é opcional. No PUT, você envia só o que quer mudar — com uma exceção: o name é obrigatório em toda atualização, mesmo que não mude. Sem ele a API responde 422.
| Campo | Descrição |
|---|---|
id | ULID, gerado automaticamente. |
name | Nome (máx. 255 caracteres). Obrigatório na criação e em toda atualização. |
sku | Código único por loja (máx. 50 caracteres). Obrigatório na criação. |
base_unit | Unidade de medida. Obrigatório na criação. |
price_type | default ou wholesale. Obrigatório na criação. |
is_available_for_sale | Visível no catálogo. |
is_industrializable | Fabricado sob demanda. |
allow_sale_without_stock | Permite venda sem saldo em estoque (sob encomenda). |
auto_wholesale_pricing | Faixas de atacado derivadas automaticamente do % de desconto. Detalhes em Preços. |
advanced_pricing | Liga o preço avançado: o preço unitário passa a aceitar 3 casas decimais. Default false. |
price_scale | Somente leitura (2 ou 3). Quantidade de casas decimais do preço unitário, derivada do advanced_pricing. |
min_purchase_quantity | Piso de compra em unidades físicas. Inteiro, mínimo 1, default 1. |
allow_fractional_quantity | Define o comportamento do mínimo: múltiplos exatos (false) ou venda fracionada (true). Default false. |
dimensions | Altura, largura, comprimento (cm) e peso (kg). |
keep_flat | Empacotamento: trava a rotação no eixo vertical; o item viaja deitado/plano. Default false. |
ship_isolated | Empacotamento: o SKU sai em volume próprio, nunca dividindo caixa com outro SKU. Default false. |
dimensions_formatted | Dimensões prontas para exibição (ex.: "1,58 m", "500g"). Só aparece com ?include_dimensions_formatted=true. |
price / min_price / max_price | default devolve price; wholesale devolve min_price e max_price (faixa da tabela). |
O
skué definido na criação e não pode ser alterado: se vier noPUT /api/products/{id}, é simplesmente ignorado.
Sublojas em modo espelho não criam SKU próprio: o catálogo vem da matriz. O
POST /api/productsresponde422 SUBSTORE_CANNOT_CREATE_SKU.
Preço avançado e quantidade mínima
Quatro campos do SKU controlam a precisão do preço unitário e o piso de compra. Todos são aceitos no POST /api/products e no PUT /api/products/{id} (exceto o price_scale, que é somente leitura) e voltam no objeto do produto.
Preço avançado (advanced_pricing)
Boolean, default false. Ligado, o preço unitário do SKU aceita 3 casas decimais (o caso clássico é o item barato vendido em volume: parafuso a R$ 0,375). Desligado, o unitário aceita 2 casas.
O price_scale é a leitura desse interruptor: inteiro 2 ou 3, derivado do advanced_pricing, somente leitura (enviar no corpo não tem efeito). Use-o para saber com quantas casas formatar o preço na sua tela e com quantas casas enviá-lo de volta para a API. As regras de validação e o efeito nos totais estão em Produtos: preços.
Quando o produto usa auto_wholesale_pricing, as faixas de atacado continuam derivadas do discount_percent, e o preço resultante de cada faixa é arredondado na escala do SKU (price_scale).
Quantidade mínima (min_purchase_quantity)
Inteiro, mínimo 1, default 1. É o piso de compra, medido sempre em unidades físicas: quantidade do item multiplicada pelo multiplicador da variação (caixa com 6, fardo com 12). Nunca conte em packs.
Comportamento do mínimo (allow_fractional_quantity)
Boolean, default false. Ele decide como o mínimo é aplicado:
false(padrão), venda em múltiplos exatos: a quantidade precisa ser um múltiplo do mínimo. O "degrau" da quantidade é o própriomin_purchase_quantity, não existe campo separado para isso.true, venda fracionada: qualquer quantidade serve, desde quequantidade × multiplicadoratinja o mínimo.
min_purchase_quantity | allow_fractional_quantity | Aceito | Rejeitado |
|---|---|---|---|
| 1 | false | 1, 2, 3, 4 | nada |
| 25 | false | 25, 50, 75 | 10, 30, 60 |
| 25 | true | 25, 30, 31, 47 | 1, 24 |
| 12 | true | 12, 13, 20 | 11 |
Exemplo de PUT /api/products/{id} com esses campos — repare que o name vai junto, porque é obrigatório em toda atualização:
{
"name": "Produto Exemplo A",
"advanced_pricing": true,
"min_purchase_quantity": 25,
"allow_fractional_quantity": false
}Publicação do anúncio: o
min_purchase_quantityprecisa ser divisível pelo multiplicador da variação. Se não for, a publicação reprova com422e a API sugere um mínimo alcançável. Detalhes em Anúncios.
Galeria
Cada produto suporta até 6 imagens. A primeira a entrar vira a thumbnail automaticamente; se ela for removida, a próxima imagem assume o lugar.
Fluxo de upload
- Suba o arquivo via Mídia. Ele retorna o
image_id. - Vincule à galeria com
POST /api/products/{id}/gallery.
O vínculo é o que protege a imagem: enquanto ela estiver solta, a rotina de limpeza pode apagá-la (ver Mídia). Cada resposta do POST devolve total e max, então dá pra saber quantas fotos ainda cabem.
| Erro | Quando acontece |
|---|---|
422 "Limite máximo de 6 fotos por produto atingido." | A galeria já tem 6 imagens. Remova uma antes. |
422 "Esta imagem já está na galeria do produto." | O image_id já está vinculado a esse produto. |
404 "Imagem não encontrada." | O image_id não existe ou não é da sua loja. |
Endpoints
Dados auxiliares
Rotas públicas (sem autenticação). Use pra popular dropdowns no seu sistema.
Fluxo: cadastro completo
| Etapa | Ação | Onde |
|---|---|---|
| 1 | Consultar enums | GET /api/global/enums/product/units |
| 2 | Criar produto | POST /api/products |
| 3 | Definir preço (default ou wholesale) | Produtos: preços |
| 4 | Definir estoque inicial | Produtos: estoque |
| 5 | Cadastrar medidas de embalagem fechada (atacado) | Produtos: medidas |
| 6 | Upload de imagens | POST /api/media/upload (Mídia) |
| 7 | Vincular à galeria | POST /api/products/{id}/gallery |
Depois disso, o produto está pronto para virar anúncio e ir ao marketplace.

