Consultando o histórico de custo dos produtos pela API
O endpoint de histórico de custo permite consultar a evolução da quantidade, do custo médio e do valor total dos produtos. Os dados podem ser usados em relatórios, integrações e ferramentas de análise, como o Power BI.
Esta consulta exige autenticação. Consulte o artigo API FoxManager: Guia Completo de Integração com Swagger para aprender a obter o token e autorizar o acesso.
Endpoint
Use uma requisição GET no endereço:
https://api.foxmanager.com.br/api/fox/product_cost_history/
O endpoint é somente para consulta e não altera informações no FoxManager.
Empresa consultada
A empresa é obrigatória e definida automaticamente pelo token utilizado na autenticação. Não é necessário informar a empresa nos parâmetros da URL.
Cada token permite consultar somente os dados da empresa à qual ele está associado. Para consultar outra empresa, use um token gerado para ela.
Não coloque o token em documentos públicos, código-fonte, planilhas compartilhadas ou capturas de tela. Guarde-o em um local seguro e restrinja o acesso ao relatório do Power BI.
Parâmetros da consulta
| Parâmetro | Obrigatório | Descrição | Exemplo |
|---|---|---|---|
start_date | Sim | Data inicial das movimentações no formato AAAA-MM-DD. | 2026-01-01 |
finish_date | Sim | Data final das movimentações no formato AAAA-MM-DD. | 2026-01-31 |
product | Não | Identificador do produto no FoxManager. | 12345 |
nfe | Não | Identificador interno da NFe no FoxManager. | 67890 |
ordering | Não | Campo usado para ordenar o resultado. O padrão é -id. | movement_date,id |
limit | Não | Quantidade por página. O padrão é 500 e o máximo é 1000. | 1000 |
offset | Não | Posição inicial da página. O padrão é zero. | 0 |
Consulta básica
Informe o período inicial e final:
GET https://api.foxmanager.com.br/api/fox/product_cost_history/?start_date=2026-01-01&finish_date=2026-01-31
Filtrar por produto
O campo product recebe o identificador numérico do produto:
GET https://api.foxmanager.com.br/api/fox/product_cost_history/?start_date=2026-01-01&finish_date=2026-01-31&product=12345
Filtrar por NFe
O campo nfe recebe o identificador interno da nota fiscal, e não o número impresso da nota:
GET https://api.foxmanager.com.br/api/fox/product_cost_history/?start_date=2026-01-01&finish_date=2026-01-31&nfe=67890
O identificador pode ser obtido pela URI retornada no endpoint de NFe:
https://api.foxmanager.com.br/api/fox/nfe/67890/
Ordenação
Por padrão, a API retorna os registros com o maior identificador primeiro.
Para ordenar do registro mais antigo para o mais recente, use:
&ordering=movement_date,id
Para ordenar do mais recente para o mais antigo, use:
&ordering=-movement_date,-id
O campo id deve ser mantido como critério adicional quando houver mais de uma movimentação na mesma data.
Estrutura da resposta
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": 10002,
"url": "https://api.foxmanager.com.br/api/fox/product_cost_history/10002/",
"movement_date": "2026-01-15",
"quantity": 10,
"average_cost": 125.50,
"total_amount": 1255.00,
"serial_number": "ABC123456",
"company": "https://api.foxmanager.com.br/api/fox/company/100/",
"product": "https://api.foxmanager.com.br/api/fox/product/12345/",
"nfe": "https://api.foxmanager.com.br/api/fox/nfe/67890/",
"nfe_item": "https://api.foxmanager.com.br/api/fox/nfe_item/98765/"
},
{
"id": 10001,
"url": "https://api.foxmanager.com.br/api/fox/product_cost_history/10001/",
"movement_date": "2026-01-01",
"quantity": 5,
"average_cost": 120.00,
"total_amount": 600.00,
"serial_number": null,
"company": "https://api.foxmanager.com.br/api/fox/company/100/",
"product": "https://api.foxmanager.com.br/api/fox/product/12345/",
"nfe": null,
"nfe_item": null
}
]
}
Campos retornados
| Campo | Tipo | Descrição |
|---|---|---|
count | Inteiro | Total de registros encontrados considerando os filtros informados. |
next | URI ou nulo | Endereço da próxima página. Será null quando não houver outra página. |
previous | URI ou nulo | Endereço da página anterior. |
results | Lista | Registros retornados na página atual. |
id | Inteiro | Identificador do histórico de custo. Também define a sequência quando existem movimentações na mesma data. |
url | URI | Endereço do registro do histórico de custo. |
movement_date | Data | Data considerada no histórico de custo, no formato AAAA-MM-DD. |
quantity | Decimal | Saldo acumulado em quantidade após a movimentação. Não representa isoladamente a quantidade movimentada na nota. |
average_cost | Decimal | Custo médio unitário do produto após a movimentação. |
total_amount | Decimal | Valor total do saldo após a movimentação. |
serial_number | Texto ou nulo | Número de série do produto relacionado ao item da NFe. Será null quando o item não possuir número de série. |
company | URI | Endereço do cadastro da empresa relacionada ao histórico. |
product | URI | Endereço do cadastro do produto relacionado ao histórico. |
nfe | URI ou nulo | Endereço da NFe relacionada. Será null para uma carga inicial sem documento fiscal. |
nfe_item | URI ou nulo | Endereço do item da NFe que originou a movimentação de custo. Será null para uma carga inicial. |
Quando nfe for null, o registro normalmente representa a carga inicial do histórico de custo. Nesse caso, nfe_item e serial_number também serão null. Os registros seguintes demonstram a evolução do saldo e do custo do produto.
Produtos controlados por número de série
Quando uma NFe movimenta mais de uma unidade de um produto controlado por número de série, a API pode retornar um registro para cada item processado. Cada registro apresenta:
- a mesma URI em
nfe; - uma URI própria em
nfe_item; - o número correspondente em
serial_number; - o saldo acumulado do produto após aquela movimentação.
Exemplo simplificado de uma NFe com duas unidades serializadas:
[
{
"quantity": 11,
"average_cost": 500.00,
"total_amount": 5500.00,
"serial_number": "SERIE-001",
"nfe": "https://api.foxmanager.com.br/api/fox/nfe/67890/",
"nfe_item": "https://api.foxmanager.com.br/api/fox/nfe_item/98765/"
},
{
"quantity": 10,
"average_cost": 500.00,
"total_amount": 5000.00,
"serial_number": "SERIE-002",
"nfe": "https://api.foxmanager.com.br/api/fox/nfe/67890/",
"nfe_item": "https://api.foxmanager.com.br/api/fox/nfe_item/98766/"
}
]
O campo quantity representa o saldo acumulado após cada movimentação. Ele não informa a quantidade vendida em cada item. Por isso, uma mesma NFe pode aparecer em registros sucessivos com quantidades diferentes.
Os campos nfe_item e serial_number fazem parte do retorno. Eles não são filtros da consulta. Para localizar os registros de uma nota, continue utilizando o parâmetro nfe.
Dúvidas sobre a interpretação dos dados
Por que uma mesma NFe pode apresentar itens com custo e outros com custo zero?
O custo é apurado separadamente para cada produto. Por isso, os itens de uma mesma NFe podem apresentar resultados diferentes.
Um produto pode aparecer com average_cost e total_amount iguais a zero quando não houver um custo anterior disponível para a movimentação, como uma entrada com valor ou uma carga inicial de custo. Isso não significa que toda a NFe esteja sem custo.
Para analisar esse caso, utilize product, nfe_item e serial_number para identificar exatamente qual produto e item originaram o registro.
Por que o mesmo produto pode aparecer várias vezes na mesma NFe?
Cada registro representa uma movimentação de custo vinculada a um item da NFe. Quando o mesmo produto está cadastrado em vários itens, especialmente em produtos controlados por número de série, a API retorna esses itens separadamente.
Nessa situação:
nfepermanece igual porque os registros pertencem à mesma nota;productpode permanecer igual porque se trata do mesmo produto;nfe_itemidentifica cada item processado;serial_numberidentifica a unidade, quando o produto possui controle por série.
Portanto, várias linhas para o mesmo produto e a mesma NFe não significam necessariamente que a nota foi processada mais de uma vez.
Por que quantity aparece em sequência?
O campo quantity apresenta o saldo acumulado do produto depois de cada movimentação. Ele não representa a quantidade vendida naquele item da nota.
Se uma NFe movimentar várias unidades separadamente, os registros poderão mostrar saldos sucessivos, como 113, 112, 111 e 110. Essa sequência demonstra a atualização do saldo a cada item processado.
Por que average_cost permanece igual e total_amount muda?
Nas saídas, o custo médio pode permanecer igual enquanto o saldo é reduzido. O campo total_amount acompanha essa alteração porque representa o valor total do saldo após a movimentação:
total_amount = quantity × average_cost
Exemplo:
| Item | Saldo após a movimentação | Custo médio | Valor total do saldo |
|---|---|---|---|
Unidade com série SERIE-001 | 11 | 500,00 | 5.500,00 |
Unidade com série SERIE-002 | 10 | 500,00 | 5.000,00 |
Os dois registros podem pertencer à mesma NFe e ao mesmo produto, mas terão nfe_item e, quando aplicável, serial_number diferentes.
Como percorrer todas as páginas
A API usa paginação com limit e offset. Para obter todos os registros:
- Faça a primeira consulta com
offset=0. - Leia os registros dentro de
results. - Verifique o campo
next. - Se
nextpossuir uma URI, faça uma nova consulta usando exatamente esse endereço. - Repita o processo até
nextretornarnull.
Não use apenas a primeira página para montar o relatório. O campo count informa o total encontrado, enquanto results contém somente os registros da página atual.
Exemplo no Power BI
No Editor do Power Query, crie uma consulta em branco e utilize um código semelhante ao exemplo abaixo. Substitua SEU_TOKEN pelo token fornecido para a integração.
let
BaseUrl = "https://api.foxmanager.com.br",
Caminho = "api/fox/product_cost_history/",
Token = "Token SEU_TOKEN",
DataInicial = "2026-01-01",
DataFinal = "2026-01-31",
Limite = 1000,
ObterPagina = (Offset as number) as record =>
Json.Document(
Web.Contents(
BaseUrl,
[
RelativePath = Caminho,
Query = [
start_date = DataInicial,
finish_date = DataFinal,
limit = Text.From(Limite),
offset = Text.From(Offset)
],
Headers = [Authorization = Token]
]
)
),
PrimeiraPagina = ObterPagina(0),
TotalPaginas = Number.RoundUp(
PrimeiraPagina[count] / Limite
),
OffsetsAdicionais =
if TotalPaginas > 1
then List.Transform({1..(TotalPaginas - 1)}, each _ * Limite)
else {},
Paginas =
{PrimeiraPagina[results]} &
List.Transform(
OffsetsAdicionais,
each ObterPagina(_)[results]
),
Registros = List.Combine(Paginas),
Tabela = Table.FromRecords(Registros)
in
Tabela
O exemplo utiliza SEU_TOKEN apenas como espaço reservado. Em uma integração definitiva, armazene a credencial de forma segura e controle quem pode editar ou baixar o arquivo do Power BI.
Atualização por período
Para reduzir o volume de dados, configure o Power BI para consultar somente o período necessário. Os campos start_date e finish_date são obrigatórios e podem ser vinculados aos parâmetros de atualização da consulta.
Ao recarregar um período já consultado, use o campo id como chave do histórico para evitar registros duplicados no modelo do Power BI.
Respostas de erro mais comuns
| Código | Significado | Como corrigir |
|---|---|---|
400 | Período ausente ou parâmetro inválido. | Informe start_date e finish_date no formato AAAA-MM-DD. |
401 | Token ausente ou inválido. | Confira o cabeçalho Authorization e utilize Token antes da chave. |
403 | Usuário sem permissão para consultar NFe e histórico de custo. | Solicite a revisão das permissões do usuário. |
404 | Registro ou endereço não encontrado. | Confira a URI e os identificadores informados. |
500 | Erro inesperado no processamento. | Se persistir, entre em contato com o suporte do FoxManager. |
Boas práticas
- Informe sempre um período compatível com o relatório.
- Utilize
limit=1000em cargas controladas para reduzir a quantidade de requisições. - Percorra todas as páginas usando o campo
next. - Use
productounfequando precisar investigar registros específicos. - Mantenha
movement_date,idna ordenação cronológica. - Trate
company,product,nfeenfe_itemcomo URIs relacionadas a outros endpoints. - Considere
serial_numbercomo opcional e aceitenullpara produtos sem controle por série. - Não exponha o token em relatórios, logs ou arquivos compartilhados.