Produtos
Vendas, margem, estoque e comportamento de recompra de cada produto da sua loja, prontos para BI e dashboards
O que esta análise responde
A API de Produtos mostra o desempenho de cada produto da loja no período que você escolher: quanto vendeu, com que margem, quanto estoque ainda resta e se os clientes que chegaram por ele voltam a comprar. Os números vêm consolidados, com os mesmos critérios usados na plataforma V4MOS.AI, então você pode levá-los direto para o seu BI sem refazer cálculos.
Perguntas que você consegue responder:
- Quais produtos vendem mais e com que margem?
- Quanto estoque eu tenho, em unidades e em dias de venda?
- Quais produtos têm muita devolução?
- Clientes que entram na loja por este produto voltam a comprar? Quanto eles valem em 180 dias?
- Como uma categoria inteira está performando?
- O que costuma ser comprado junto com este produto, e o que o cliente compra depois?
- Quais cupons e canais de aquisição trazem vendas deste produto?
Como começar
Base URL: https://data.v4mos.ai. Todas as chamadas exigem as credenciais da API e o organizationId — veja Autenticação.
1. Descubra o identificador da loja
Chame GET /v1/products/integrations?organizationId=…. Cada loja da organização vem com um sourceIntegrationId: é esse valor que você envia como integrationId em todos os outros endpoints de Produtos.
Por que não usar a App Key da VTEX?
A App Key é uma credencial: ela pode ser trocada a qualquer momento e a mesma chave pode estar ligada a mais de uma loja ou organização. O sourceIntegrationId identifica a loja de forma estável nos dados da V4MOS.AI, por isso é ele que os endpoints esperam.
2. Liste os produtos
GET /v1/products traz uma linha por produto, com as métricas do período, paginada e ordenável.
3. Veja os totais por categoria
GET /v1/products/categories traz os totais de cada categoria para a mesma seleção da listagem.
4. Aprofunde em um produto
GET /v1/products/{productId} traz o detalhe completo de um produto e GET /v1/products/{productId}/series traz a evolução diária ou semanal das vendas.
curl "https://data.v4mos.ai/v1/products?organizationId=SEU_ORGANIZATION_ID&integrationId=SEU_SOURCE_INTEGRATION_ID&dateFrom=2026-09-01&dateTo=2026-09-30&sortBy=netSales&pageSize=50" \
-H "x-client-id: seu_client_id" \
-H "x-client-secret: seu_client_secret"| Pergunta | Endpoint |
|---|---|
| Quais lojas posso consultar e qual identificador usar? | GET /v1/products/integrations |
| Quais produtos vendem mais, com que margem e quanto estoque têm? | GET /v1/products |
| Como cada categoria está performando? | GET /v1/products/categories |
| Tudo sobre um produto: funil, recompra, cesta, cupons, canais | GET /v1/products/{productId} |
| Como as vendas de um produto evoluíram dia a dia ou semana a semana? | GET /v1/products/{productId}/series |
Métricas
Valores monetários estão na moeda da loja e não incluem frete, impostos, serviços, mídia, taxas nem logística reversa. Taxas e proporções vêm como decimal: 0.3 significa 30%.
| Campo | O que é | Como é calculado | Unidade |
|---|---|---|---|
grossSales | Total vendido | Valor faturado dos itens do produto no período, antes das devoluções | Moeda |
netSales | Faturamento | Total vendido menos as devoluções registradas | Moeda |
grossUnits / netUnits | Unidades vendidas | Unidades faturadas / unidades faturadas menos as devolvidas | Unidades |
averageTicket | Ticket médio | Faturamento ÷ pedidos que contêm o produto | Moeda |
cogs | CMV | Custo das unidades que o cliente manteve (não devolveu) | Moeda |
marginTotal | Margem | Faturamento − CMV. Margem do produto antes de outras despesas variáveis | Moeda |
marginAverage | Margem % | Margem ÷ Faturamento | Decimal (0–1) |
newCustomers | Clientes novos | Clientes cuja primeira compra na loja aconteceu no período e incluiu o produto | Clientes |
recurringCustomers | Clientes recorrentes | Clientes que compraram o produto no período e já tinham comprado na loja antes | Clientes |
entryCustomers | Clientes de entrada | Clientes que "entraram" na loja por este produto no período (primeira compra contendo o produto) | Clientes |
matureEntryCustomers | Clientes de entrada maduros | Clientes de entrada que já completaram 180 dias desde a primeira compra | Clientes |
ltv180 | LTV 180 dias | Receita líquida média em 180 dias dos clientes de entrada maduros | Moeda |
repurchaseRate180 | Recompra em 180 dias | Parcela dos clientes de entrada maduros que fizeram outro pedido (de qualquer produto) em até 180 dias | Decimal (0–1) |
ltvToDate | LTV até agora | Receita líquida média acumulada até hoje por todos os clientes de entrada, maduros ou não | Moeda |
repurchaseRateToDate | Recompra até agora | Parcela de todos os clientes de entrada que já voltaram a comprar | Decimal (0–1) |
cohortElapsedDaysAverage | Idade média do grupo | Média de dias desde a primeira compra dos clientes de entrada (no máximo 180) | Dias |
availableStock | Estoque disponível | Estoque atual menos o reservado, somando os SKUs do produto | Unidades |
velocity30d | Velocidade de venda | Unidades vendidas por dia nos últimos 30 dias completos (independe do período escolhido) | Unidades/dia |
daysOfStock | Dias de estoque | Estoque disponível ÷ velocidade de venda | Dias |
returnRate | Taxa de devolução | Unidades devolvidas ÷ unidades vendidas | Decimal (0–1) |
Período e atualização
- Vendas, clientes e margem seguem o período
dateFrom–dateTo. - Catálogo, status e estoque mostram a foto mais recente, qualquer que seja o período.
asOfé a data/hora da última atualização dos dados de origem. Mostre-o ao lado dos números para indicar o quão recentes eles são.inventoryFreshnessindica se o estoque está atualizado (fresh), desatualizado há mais de 24 horas (stale) ou sem leitura (missing).inventoryUpdatedAttraz a data da última leitura.
LTV e recompra: o grupo de entrada de 180 dias
Um cliente "entra" por um produto quando a primeira compra dele na loja contém esse produto. Para medir LTV e recompra de forma justa, cada cliente precisa de 180 dias desde a primeira compra — até lá, ele ainda está "amadurecendo".
ltv180erepurchaseRate180usam apenas os clientes que já completaram 180 dias. Leia-os junto commatureEntryCustomers/entryCustomerspara saber quantos clientes estão por trás do número.cohortStateresume a situação:mature(todos maduros),partial(parte madura),maturing(ninguém maduro ainda) ouno_base(nenhum cliente de entrada no período).- Para grupos recentes, use
ltvToDateerepurchaseRateToDate, que consideram todos os clientes. Eles crescem com o tempo, então compare-os sempre olhandocohortElapsedDaysAverage.
Quando um valor vem como N/D
null significa N/D (não disponível) — nunca zero. O objeto ndReasons explica o motivo e coverage mostra quanto dos dados de origem estava completo (de 0 a 1):
| Situação | Onde aparece |
|---|---|
Margem e CMV ocultos porque falta valor de venda (incomplete_gross_value) ou custo (incomplete_cost) de alguma unidade | ndReasons.margin, coverage.grossValue, coverage.cost |
Margem % sem faturamento no período (no_net_sales) | ndReasons.averageMargin |
Dias de estoque sem venda recente (no_movement) ou estoque não monitorado/ilimitado | ndReasons.daysOfStock, inventoryState, coverage.inventory |
LTV e recompra sem clientes maduros (no_base, maturing) | ndReasons.ltv180, ndReasons.repurchaseRate180, coverage.matureCohort |
Taxa de devolução sem vendas (no_sales_base) ou em loja que nunca registrou devolução (no_returns_coverage) | ndReasons.returnRate |
Filtros e ordenação
GET /v1/products e GET /v1/products/categories aceitam os mesmos filtros:
- Busca:
searchencontra produtos cujo nome contém o texto (sem diferenciar maiúsculas e minúsculas, até 120 caracteres). - Status:
status=active,inactiveouall(padrão). - Categorias:
categoryIdsaceita até 50 categorias, separadas por vírgula (categoryIds=1,12) ou repetidas (categoryIds=1&categoryIds=12). Um produto entra se pertencer a qualquer uma delas, inclusive por uma subcategoria.categoryId(uma só categoria) ainda funciona, mas prefiracategoryIds. - Faixas de métricas (limites inclusivos):
minNetSales/maxNetSales,minMarginTotal/maxMarginTotal,minMarginAverage/maxMarginAverageeminAvailableStock/maxAvailableStock. A margem % é decimal:minMarginAverage=0.3significa "margem de pelo menos 30%". Ominnão pode ser maior que omax. - Paginação (só na listagem):
page(padrão1) epageSize(padrão25, máximo100). A resposta trazpagination.totalepagination.totalPages. - Ordenação (só na listagem):
sortBycom um destes campos —productName,grossSales,netSales(padrão),netUnits,averageTicket,marginAverage,marginTotal,newCustomers,recurringCustomers,ltv180,repurchaseRate180,ltvToDate,repurchaseRateToDate,entryCustomers,matureEntryCustomers,availableStock,daysOfStock,returnRate,updatedAt— esortOrder=asc|desc(padrãodesc). Valores N/D ficam sempre no fim. - Colunas:
columnsrecebe uma lista de métricas separadas por vírgula (por exemplocolumns=netSales,marginTotal,daysOfStock) e devolve só elas. Identificação, status, cobertura e motivos de N/D sempre vêm. - Categorias na listagem: a listagem traz também os totais por categoria em
categories. Se você já usaGET /v1/products/categories, envieincludeCategories=falsepara receber a listagem mais rápido.
N/D nunca entra em uma faixa
Um produto com margem ou estoque N/D não satisfaz nenhum filtro sobre essa métrica. Por exemplo, minMarginTotal=0 exclui os produtos cuja margem está oculta por falta de custo.
Regras importantes
Quando a margem não aparece
A margem (marginTotal, marginAverage) e o CMV (cogs) só aparecem quando todas as unidades do produto no período têm valor de venda e custo cadastrados. Se faltar o custo de algumas unidades, o custo somado ficaria menor que o real e a margem pareceria maior do que é — por isso o valor fica N/D, com o motivo em ndReasons.margin. Para liberar a margem, complete o cadastro de custo dos produtos na plataforma de e-commerce.
Totais de categoria x soma da página
Os totais de categories consideram todos os produtos filtrados, não só os da página atual, e continuam corretos em qualquer página ou ordenação. Pedidos e clientes são recontados (um pedido com vários produtos da categoria conta uma vez) e as taxas são recalculadas a partir dos totais. Com faixas de métricas, cada categoria soma apenas os produtos que estão dentro das faixas; categorias sem nenhum produto na faixa não aparecem.
Não some níveis diferentes
Somar as linhas de uma página não reproduz o total da categoria. E um departamento já inclui suas subcategorias: use depth e parentCategoryId para não somar o mesmo valor duas vezes.
O detalhe do produto funciona por blocos
GET /v1/products/{productId} é formado por blocos independentes — resumo, funil, grupo de entrada (coorte), comprados juntos, retenção, frequência de compra, comprado depois, cupons e canais de aquisição. Cada bloco traz seu próprio state e reason:
- A resposta é
200sempre que o produto existe para a organização e a loja. Um bloco pode vir comstate: "error"ou sem dados enquanto os outros funcionam normalmente — trate cada bloco separadamente. 404significa que o produto não existe nessa loja;400, que algum parâmetro é inválido.- Nem todo bloco usa o período pedido.
periodAppliedinforma se o bloco seguiudateFrom/dateToewindowinforma o intervalo realmente medido. Comprados juntos e comprado depois usam os últimos 12 meses; o grupo de entrada usa os últimoscohortWindowMonthsmeses de entrada do produto. - Use o
asOfde cada bloco ao lado dos números dele. OasOfda raiz é o mais antigo entre os blocos.
Atualização dos dados
As respostas podem levar até 5 minutos para refletir dados novos (até 30 minutos na série de vendas). Um bloco que veio com error não é reaproveitado: uma nova chamada tenta buscá-lo de novo.
Não monitore a saúde da integração só pelo status HTTP
Mesmo que todas as fontes falhem, o detalhe responde 200 com todos os blocos em error. Verifique o state de cada bloco.
Grupos de entrada se sobrepõem entre produtos
Um cliente cuja primeira compra teve vários produtos entra no grupo de cada um deles. Por isso, as linhas de coorte (e também entryCustomers, newCustomers, ltv180 e afins) não podem ser somadas entre produtos — o mesmo cliente seria contado mais de uma vez. O campo overlappingRows: true no bloco de coorte lembra essa regra. O mesmo vale para comprados juntos e comprado depois: um pedido alimenta várias linhas.
Devoluções são um piso
Devoluções registradas depois que o pedido é finalizado podem não ser capturadas. Por isso returnRate é um valor mínimo (a devolução real pode ser maior) e faturamento e margem podem estar levemente acima do real. O bloco de resumo do detalhe declara isso em summary.returnMeasurement.
Parâmetros comuns
| Parâmetro | Obrigatório | Descrição |
|---|---|---|
organizationId | Sim | UUID da organização. Exigido em todos os endpoints. |
integrationId | Sim (exceto em /integrations) | O sourceIntegrationId retornado por GET /v1/products/integrations. Nunca a App Key da VTEX. |
dateFrom / dateTo | Não | Período no formato AAAA-MM-DD. Padrão: os últimos 30 dias até hoje. Máximo de 365 dias, sem datas futuras, e dateFrom não pode ser depois de dateTo. |
productId | Sim (no caminho, endpoints de um produto) | O productId exatamente como veio na listagem. IDs com barras (como os da Shopify) precisam ser codificados na URL. |
Endpoints disponíveis
- getLojas VTEX disponíveis no dashboard de produtos
/v1/products/integrationsLista as lojas da organização com o identificador que os demais endpoints de Produtos esperam em integrationId. - getCategorias de produtos consolidadas
/v1/products/categoriesRetorna os totais de cada categoria (departamentos e subcategorias) para a mesma seleção de GET /v1/products: loja, período, busca,… - getProdutos consolidados
/v1/productsRetorna uma linha por produto com vendas, margem, estoque, devoluções e métricas de recompra do período, além dos totais por categoria em… - getSérie diária ou semanal de vendas de um produto
/v1/products/{productId}/seriesRetorna a evolução de faturamento, unidades, pedidos, custo e margem de um produto, dia a dia (granularity=day) ou em blocos de 7 dias… - getDetalhe do produto com blocos independentes
/v1/products/{productId}Retorna tudo sobre um produto em blocos independentes: resumo de métricas com comparação ao período anterior, funil do GA4, coorte de…