Produtos

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"
PerguntaEndpoint
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, canaisGET /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%.

CampoO que éComo é calculadoUnidade
grossSalesTotal vendidoValor faturado dos itens do produto no período, antes das devoluçõesMoeda
netSalesFaturamentoTotal vendido menos as devoluções registradasMoeda
grossUnits / netUnitsUnidades vendidasUnidades faturadas / unidades faturadas menos as devolvidasUnidades
averageTicketTicket médioFaturamento ÷ pedidos que contêm o produtoMoeda
cogsCMVCusto das unidades que o cliente manteve (não devolveu)Moeda
marginTotalMargemFaturamento − CMV. Margem do produto antes de outras despesas variáveisMoeda
marginAverageMargem %Margem ÷ FaturamentoDecimal (0–1)
newCustomersClientes novosClientes cuja primeira compra na loja aconteceu no período e incluiu o produtoClientes
recurringCustomersClientes recorrentesClientes que compraram o produto no período e já tinham comprado na loja antesClientes
entryCustomersClientes de entradaClientes que "entraram" na loja por este produto no período (primeira compra contendo o produto)Clientes
matureEntryCustomersClientes de entrada madurosClientes de entrada que já completaram 180 dias desde a primeira compraClientes
ltv180LTV 180 diasReceita líquida média em 180 dias dos clientes de entrada madurosMoeda
repurchaseRate180Recompra em 180 diasParcela dos clientes de entrada maduros que fizeram outro pedido (de qualquer produto) em até 180 diasDecimal (0–1)
ltvToDateLTV até agoraReceita líquida média acumulada até hoje por todos os clientes de entrada, maduros ou nãoMoeda
repurchaseRateToDateRecompra até agoraParcela de todos os clientes de entrada que já voltaram a comprarDecimal (0–1)
cohortElapsedDaysAverageIdade média do grupoMédia de dias desde a primeira compra dos clientes de entrada (no máximo 180)Dias
availableStockEstoque disponívelEstoque atual menos o reservado, somando os SKUs do produtoUnidades
velocity30dVelocidade de vendaUnidades vendidas por dia nos últimos 30 dias completos (independe do período escolhido)Unidades/dia
daysOfStockDias de estoqueEstoque disponível ÷ velocidade de vendaDias
returnRateTaxa de devoluçãoUnidades devolvidas ÷ unidades vendidasDecimal (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.
  • inventoryFreshness indica se o estoque está atualizado (fresh), desatualizado há mais de 24 horas (stale) ou sem leitura (missing). inventoryUpdatedAt traz 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".

  • ltv180 e repurchaseRate180 usam apenas os clientes que já completaram 180 dias. Leia-os junto com matureEntryCustomers / entryCustomers para saber quantos clientes estão por trás do número.
  • cohortState resume a situação: mature (todos maduros), partial (parte madura), maturing (ninguém maduro ainda) ou no_base (nenhum cliente de entrada no período).
  • Para grupos recentes, use ltvToDate e repurchaseRateToDate, que consideram todos os clientes. Eles crescem com o tempo, então compare-os sempre olhando cohortElapsedDaysAverage.

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çãoOnde aparece
Margem e CMV ocultos porque falta valor de venda (incomplete_gross_value) ou custo (incomplete_cost) de alguma unidadendReasons.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/ilimitadondReasons.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: search encontra produtos cujo nome contém o texto (sem diferenciar maiúsculas e minúsculas, até 120 caracteres).
  • Status: status=active, inactive ou all (padrão).
  • Categorias: categoryIds aceita 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 prefira categoryIds.
  • Faixas de métricas (limites inclusivos): minNetSales/maxNetSales, minMarginTotal/maxMarginTotal, minMarginAverage/maxMarginAverage e minAvailableStock/maxAvailableStock. A margem % é decimal: minMarginAverage=0.3 significa "margem de pelo menos 30%". O min não pode ser maior que o max.
  • Paginação (só na listagem): page (padrão 1) e pageSize (padrão 25, máximo 100). A resposta traz pagination.total e pagination.totalPages.
  • Ordenação (só na listagem): sortBy com um destes campos — productName, grossSales, netSales (padrão), netUnits, averageTicket, marginAverage, marginTotal, newCustomers, recurringCustomers, ltv180, repurchaseRate180, ltvToDate, repurchaseRateToDate, entryCustomers, matureEntryCustomers, availableStock, daysOfStock, returnRate, updatedAt — e sortOrder=asc|desc (padrão desc). Valores N/D ficam sempre no fim.
  • Colunas: columns recebe uma lista de métricas separadas por vírgula (por exemplo columns=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á usa GET /v1/products/categories, envie includeCategories=false para 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 é 200 sempre que o produto existe para a organização e a loja. Um bloco pode vir com state: "error" ou sem dados enquanto os outros funcionam normalmente — trate cada bloco separadamente.
  • 404 significa que o produto não existe nessa loja; 400, que algum parâmetro é inválido.
  • Nem todo bloco usa o período pedido. periodApplied informa se o bloco seguiu dateFrom/dateTo e window informa o intervalo realmente medido. Comprados juntos e comprado depois usam os últimos 12 meses; o grupo de entrada usa os últimos cohortWindowMonths meses de entrada do produto.
  • Use o asOf de cada bloco ao lado dos números dele. O asOf da 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âmetroObrigatórioDescrição
organizationIdSimUUID da organização. Exigido em todos os endpoints.
integrationIdSim (exceto em /integrations)O sourceIntegrationId retornado por GET /v1/products/integrations. Nunca a App Key da VTEX.
dateFrom / dateToNãoPerí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.
productIdSim (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

Nesta página