Consulta de notas fiscais e CT-e, pedido de importação pela chave, laudos de produto (com checklist) e movimento de saldo diário.
Autenticação em todos os exemplos: veja Autenticação. Teste no navegador pelo Swagger ou importe a coleção do Postman.
| Endpoint | Métodos | Para que serve |
|---|---|---|
notaFiscal |
GET | Consulta resumida de uma nota fiscal |
importarNotaFiscal |
GET, POST | Solicita a importação de NF-e pela chave |
conhecimentoTransporte |
GET | Consulta resumida de um CT-e |
importarConhecimentoTransporte |
GET, POST | Solicita a importação de CT-e pela chave |
laudoProduto |
GET, POST, PUT, DELETE | Laudo de produto (qualidade) com checklist |
movimentoSaldoDia |
GET | Saldo diário físico x fiscal por cliente e produto |
Consulta resumida de uma nota fiscal. Devolve a identificação e a situação de uma NF-e que já existe no PetroW, localizada por id_nota_fiscal ou pela chave de 44 dígitos. Só leitura. Acesso com perfil cliente ou de filial só vê notas do próprio cliente ou filial.
/v1/terceiro/notaFiscalConsulta nota fiscal por id ou chave
Perfis: App, Rede, Filial, Cliente, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_nota_fiscal |
integer | sim | Id da nota fiscal. (Ou chave (44 dígitos da NF-e; aceita com máscara).) |
curl -s -X GET "$BASE/v1/terceiro/notaFiscal?$AUTH&id_nota_fiscal="
Resposta:
{
"status": "ok",
"id_nota_fiscal": 1001,
"chave": "41260100000000000100550010000012341000012345",
"numero": 1234,
"serie": 1,
"situacao": "AUTORIZADA"
}
Erros específicos: 400 — {"errors":{"id_nota_fiscal":"Inválido"}}: sem id e sem chave válida, ou chave não encontrada.; 400 — {"errors":{"registro":"Falha ao localizar"}}: o id não existe no app.; 403 — {"errors":{"acesso":"Negado"}}: fora do escopo do acesso..
Solicita a importação de NF-e pela chave. Coloca a chave de NF-e numa fila de importação. Não recebe o XML: o PetroW verifica periodicamente se o XML já está no repositório fiscal; quando o encontra, marca xml_ok = S e, na importação seguinte, cria a nota no PetroW e preenche id_nota_fiscal. A importação só é concluída se a nota pertencer a uma filial do app. Use o GET para acompanhar o andamento.
/v1/terceiro/importarNotaFiscalConsulta o andamento
O GET não restringe pelo escopo do acesso (cliente ou filial): consulta qualquer pedido do app.
Perfis: App, Rede, Filial, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_importar_nota_fiscal |
integer | sim | Id do pedido de importação (Ou chave (44 dígitos).) |
curl -s -X GET "$BASE/v1/terceiro/importarNotaFiscal?$AUTH&id_importar_nota_fiscal="
Resposta:
{
"status": "ok",
"id_importar_nota_fiscal": 55,
"chave": "41260100000000000100550010000012341000012345",
"xml_ok": "S",
"id_nota_fiscal": 1001
}
Erros específicos: 400 — {"errors":{"id_importar_nota_fiscal":"Inválido"}}: sem id/chave válida.; 400 — {"errors":{"registro":"Falha ao localizar"}}: o id não existe no app..
/v1/terceiro/importarNotaFiscalColoca a chave na fila de importação
A chave vai na query string, não no corpo. O corpo é ignorado.
Perfis: App, Rede, Filial, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
chave |
string | sim | Chave de acesso da NF-e (44 dígitos; aceita máscara). |
curl -s -X POST "$BASE/v1/terceiro/importarNotaFiscal?$AUTH&chave="
Resposta:
{
"status": "ok",
"id_importar_nota_fiscal": 55
}
Erros específicos: 400 — {"errors":{"chave":"Inválido"}}: chave inválida.; 400 — {"errors":{"exception":""}}: erro de validação ao gravar. Chave já enviada antes: "Dados já cadastrados (id)"..
Consulta resumida de um CT-e. Devolve a identificação e a situação de um conhecimento de transporte (CT-e) que já existe no PetroW, por id ou chave. Acesso com perfil filial ou rede só vê CT-e da filial; acesso com perfil cliente só vê CT-e em que o cliente é tomador, remetente, destinatário, expedidor ou recebedor.
/v1/terceiro/conhecimentoTransporteConsulta CT-e por id ou chave
Na busca por chave, só o formato (44 dígitos) é verificado.
Perfis: App, Rede, Filial, Cliente, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_conhecimento_transporte |
integer | sim | Id do CT-e (Ou chave (44 dígitos).) |
curl -s -X GET "$BASE/v1/terceiro/conhecimentoTransporte?$AUTH&id_conhecimento_transporte="
Resposta:
{
"status": "ok",
"id_conhecimento_transporte": 501,
"chave": "41260100000000000100570010000004561000045678",
"numero": 456,
"serie": 1,
"situacao": "AUTORIZADA"
}
Erros específicos: 400 — {"errors":{"id_conhecimento_transporte":"Inválido"}}.; 400 — {"errors":{"registro":"Falha ao localizar"}}: o id não existe no app.; 403 — {"errors":{"acesso":"Negado"}}: fora do escopo do acesso..
Solicita a importação de CT-e pela chave. Coloca a chave de CT-e numa fila de importação. Não recebe o XML: o PetroW verifica periodicamente se o XML já está no repositório fiscal; quando o encontra, marca xml_ok = S e, na importação seguinte, cria o CT-e no PetroW e preenche id_conhecimento_transporte. Use o GET para acompanhar o andamento.
/v1/terceiro/importarConhecimentoTransporteConsulta o andamento
O GET não restringe pelo escopo do acesso (cliente ou filial): consulta qualquer pedido do app.
Perfis: App, Rede, Filial, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_importar_conhecimento_transporte |
integer | sim | Id do pedido de importação (Ou chave (44 dígitos).) |
curl -s -X GET "$BASE/v1/terceiro/importarConhecimentoTransporte?$AUTH&id_importar_conhecimento_transporte="
Resposta:
{
"status": "ok",
"id_importar_conhecimento_transporte": 55,
"chave": "41260100000000000100550010000012341000012345",
"xml_ok": "S",
"id_conhecimento_transporte": 1001
}
Erros específicos: 400 — {"errors":{"id_conhecimento_transporte":"Inválido"}}: sem id ou chave válida (o erro usa esse nome de campo).; 400 — {"errors":{"registro":"Falha ao localizar"}}: o id não existe no app..
/v1/terceiro/importarConhecimentoTransporteColoca a chave na fila de importação
A chave vai na query string, não no corpo. O corpo é ignorado.
Perfis: App, Rede, Filial, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
chave |
string | sim | Chave de acesso do CT-e (44 dígitos; aceita máscara). |
curl -s -X POST "$BASE/v1/terceiro/importarConhecimentoTransporte?$AUTH&chave="
Resposta:
{
"status": "ok",
"id_importar_conhecimento_transporte": 55
}
Erros específicos: 400 — {"errors":{"chave":"Inválido"}}: chave inválida.; 400 — {"errors":{"exception":""}}: erro de validação ao gravar. Chave já enviada antes: "Dados já cadastrados (id)"..
Laudo de produto (qualidade) com checklist. Cria, consulta, altera e desativa laudos de produto. O laudo nasce pendente (aprovado = X). Aprovar ou reprovar não é feito por esta API; depois de aprovado ou reprovado, o laudo não pode mais ser alterado. O checklist é escolhido pela configuração de checklist de laudo mais específica para filial × fornecedor × produto × grade × tipo. O GET lista todas as perguntas desse checklist (respondidas ou não); POST e PUT gravam as respostas por id_checklist_item (criam a resposta ou alteram a existente). Acesso com perfil filial ou rede só acessa laudos da filial; acesso com perfil cliente só consulta laudos ligados a ordens do cliente.
/v1/terceiro/laudoProdutoConsulta um laudo com checklist, vínculos e PDF
Perfis: App, Rede, Filial, Cliente, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_laudo_produto |
integer | sim | Id do laudo |
curl -s -X GET "$BASE/v1/terceiro/laudoProduto?$AUTH&id_laudo_produto="
Resposta:
{
"status": "ok",
"id_laudo_produto": 77,
"id_tx_estabelecimento": 3,
"id_fornecedor": 12,
"id_produto": 5,
"quantidade": 30000,
"unidade": "L",
"numero": "LAU-001",
"data_amostra": "2026-11-10",
"data_laudo": "2026-11-10",
"observacao": "",
"ativo": true,
"tipo": "",
"id_produto_grade": 0,
"id_tx_pessoa": 0,
"data_hora": null,
"aprovado": "X",
"origem": "",
"lacres": "123;124",
"checklist": {
"descricao": "LAUDO DE RECEBIMENTO",
"observacoes": "",
"rodape": "",
"respostas": [
{
"id_checklist_item": 48,
"pergunta": "ASPECTO",
"resposta": "LÍMPIDO",
"aprovado": true,
"observacao": ""
},
{
"id_checklist_item": 49,
"pergunta": "COR",
"resposta": "",
"aprovado": false,
"observacao": ""
}
]
},
"ordem": [
{
"tipo": "D",
"id_ordem": 9001,
"produtos": [
{
"id_produto": 5
}
]
}
],
"estoque": [
{
"id_estoque": 10,
"observacao": ""
}
],
"pedido": [
{
"id_pedido": 300,
"tipo": "V",
"observacao": "",
"ativo": true,
"itens": [
{
"descricao": "ETANOL",
"id_produto": 5,
"ativo": true
}
]
}
],
"conhecimento_transporte": [
{
"chave": "41260100000000000100570010000004561000045678",
"numero": 456,
"serie": 1
}
],
"nota_fiscal": [
{
"chave": "41260100000000000100550010000012341000012345",
"numero": 1234,
"serie": 1
}
],
"batelada": [
{
"id_batelada": 20,
"ativo": true,
"produtos": [
{
"id_produto": 5
}
]
}
],
"contrato_coleta": [
{
"id_contrato_coleta": 40
}
],
"pdf_base64": "JVBERi0xLjQK..."
}
Erros específicos: 400 — {"errors":{"id_laudo_produto":"Inválido"}}.; 400 — {"errors":{"registro":"Falha ao localizar"}}: o id não existe no app.; 403 — {"errors":{"acesso":"Negado"}}: fora do escopo do acesso..
/v1/terceiro/laudoProdutoCria um laudo (e respostas do checklist)
Laudo e respostas são gravados juntos: qualquer erro desfaz tudo. Sem 'checklist' no corpo, nenhuma resposta é gravada.
Perfis: App, Rede, Filial, Cliente, Pessoa
Corpo (JSON objeto)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_tx_estabelecimento |
integer | não | Filial do laudo. Alternativa: cpf_cnpj_tx_estabelecimento. Sem ela, usa a filial do acesso com perfil filial (0 para os demais tipos). |
cpf_cnpj_tx_estabelecimento |
string | não | CNPJ da filial (usado se id_tx_estabelecimento não vier). |
id_fornecedor |
integer | não | Fornecedor. Alternativa: cpf_cnpj_fornecedor. |
cpf_cnpj_fornecedor |
string | não | CNPJ/CPF do fornecedor (usado se id_fornecedor não vier). |
id_produto |
integer | não | Produto (só o id). |
id_produto_grade |
integer | não | Grade do produto (padrão 0) |
quantidade |
number | não | Quantidade (padrão 0) |
unidade |
string | não | L, M3, KG, TON ou UN (padrão L) |
numero |
string | não | Número do laudo |
data_amostra |
date | não | Data da amostra, AAAA-MM-DD. Formato inválido = 400. Sem o campo: no POST, a data de hoje; no PUT, a data atual é mantida. |
data_laudo |
date | não | Data do laudo, AAAA-MM-DD. Mesmas regras de data_amostra. |
tipo |
string | não | Tipo do laudo (texto livre; também usado para escolher o checklist). |
origem |
string | não | Origem |
lacres |
string | não | Lacres |
observacao |
string | não | Observação |
checklist |
array|object | não | Respostas do checklist: lista de {id_checklist_item, resposta, observacao} ou objeto {"respostas":[…]} (o mesmo formato devolvido no GET). |
curl -s -X POST "$BASE/v1/terceiro/laudoProduto?$AUTH" \
-H 'Content-Type: application/json' \
-d '{"cpf_cnpj_tx_estabelecimento": "00.000.000/0001-00", "cpf_cnpj_fornecedor": "11.111.111/0001-11", "id_produto": 5, "quantidade": 30000, "unidade": "L", "numero": "LAU-001", "data_amostra": "2026-11-10", "data_laudo": "2026-11-10", "lacres": "123;124", "checklist": [{"id_checklist_item": 48, "resposta": "LÍMPIDO", "observacao": ""}, {"id_checklist_item": 49, "resposta": "INCOLOR"}]}'
Resposta:
{
"status": "ok",
"id_laudo_produto": 77
}
Erros específicos: 400 — {"errors":{"body":"O conteúdo não é um JSON válido"}}.; 403 — {"errors":{"acesso":"Negado"}}: filial fora do escopo do acesso.; 400 — {"errors":{"checklist":"Nenhum checklist relacionado ao laudo (estabelecimento x fornecedor x produto x grade)"}}: o corpo traz checklist, mas não há configuração de checklist para o laudo.; 400 — {"errors":{"checklist":"id_checklist_item é obrigatório em cada resposta"}}.; 400 — {"errors":{"checklist":"id_checklist_item N não pertence ao checklist do laudo (M)"}}.; 400 — {"errors":{"exception":""}}: erro de validação do laudo, da grade ou das respostas (ex.: "Dados já cadastrados (id)")..
/v1/terceiro/laudoProdutoAltera um laudo pendente (e respostas)
Atenção: o PUT não é parcial. Todos os campos do laudo são regravados com o valor do corpo ou com o padrão (0, '', 'L'): mande o laudo completo. data_amostra e data_laudo só mudam quando enviadas. As respostas do checklist só mudam para os itens enviados.
Perfis: App, Rede, Filial, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_laudo_produto |
integer | sim | Id do laudo |
Corpo (JSON objeto)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_tx_estabelecimento |
integer | não | Filial do laudo. Alternativa: cpf_cnpj_tx_estabelecimento. Sem ela, usa a filial do acesso com perfil filial (0 para os demais tipos). |
cpf_cnpj_tx_estabelecimento |
string | não | CNPJ da filial (usado se id_tx_estabelecimento não vier). |
id_fornecedor |
integer | não | Fornecedor. Alternativa: cpf_cnpj_fornecedor. |
cpf_cnpj_fornecedor |
string | não | CNPJ/CPF do fornecedor (usado se id_fornecedor não vier). |
id_produto |
integer | não | Produto (só o id). |
id_produto_grade |
integer | não | Grade do produto (padrão 0) |
quantidade |
number | não | Quantidade (padrão 0) |
unidade |
string | não | L, M3, KG, TON ou UN (padrão L) |
numero |
string | não | Número do laudo |
data_amostra |
date | não | Data da amostra, AAAA-MM-DD. Formato inválido = 400. Sem o campo: no POST, a data de hoje; no PUT, a data atual é mantida. |
data_laudo |
date | não | Data do laudo, AAAA-MM-DD. Mesmas regras de data_amostra. |
tipo |
string | não | Tipo do laudo (texto livre; também usado para escolher o checklist). |
origem |
string | não | Origem |
lacres |
string | não | Lacres |
observacao |
string | não | Observação |
checklist |
array|object | não | Respostas do checklist: lista de {id_checklist_item, resposta, observacao} ou objeto {"respostas":[…]} (o mesmo formato devolvido no GET). |
curl -s -X PUT "$BASE/v1/terceiro/laudoProduto?$AUTH&id_laudo_produto=" \
-H 'Content-Type: application/json' \
-d '{"id_tx_estabelecimento": 3, "id_fornecedor": 12, "id_produto": 5, "quantidade": 30000, "unidade": "L", "numero": "LAU-001", "data_amostra": "2026-11-10", "data_laudo": "2026-11-10", "checklist": {"respostas": [{"id_checklist_item": 49, "resposta": "INCOLOR", "observacao": "conferido"}]}}'
Resposta:
{
"status": "ok"
}
Erros específicos: 400 — {"errors":{"id_laudo_produto":"Inválido"}}.; 400 — {"errors":{"body":"O conteúdo não é um JSON válido"}}.; 400 — {"errors":{"registro":"Falha ao localizar"}}: o id não existe no app.; 403 — {"errors":{"acesso":"Negado"}}: fora do escopo do acesso.; 400 — laudo já aprovado ou reprovado não pode ser alterado (erro no campo aprovado).; 400 — os mesmos erros de checklist do POST..
/v1/terceiro/laudoProdutoDesativa um laudo
Desativa (ativo = N); não apaga.
Perfis: App, Rede, Filial, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id_laudo_produto |
integer | sim | Id do laudo |
curl -s -X DELETE "$BASE/v1/terceiro/laudoProduto?$AUTH&id_laudo_produto="
Resposta:
{
"status": "ok"
}
Erros específicos: 400 — {"errors":{"id_laudo_produto":"Inválido"}}.; 400 — {"errors":{"registro":"Falha ao localizar"}}: o id não existe no app.; 403 — {"errors":{"acesso":"Negado"}}: fora do escopo do acesso.; 400 — {"errors":{"exception":"…"}}: falha ao desativar..
Saldo diário físico x fiscal por cliente e produto. Lista, por dia, o saldo anterior, as entradas, as saídas e o saldo final físico e fiscal (e as diferenças fiscal − físico) de cada cliente e produto. Os números vêm de um consolidado que o PetroW recalcula periodicamente, então movimentos muito recentes podem ainda não aparecer. Paginado (máx. 50 por página). O escopo do acesso filtra cliente e filial.
/v1/terceiro/movimentoSaldoDiaLista o movimento e o saldo por dia
Ordenado por cliente, produto e dia. Sem linhas: data = [] e param só com _size e _page.
Perfis: App, Rede, Filial, Pessoa
Parâmetros (query)
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
data_inicial |
date | não | Primeiro dia (AAAA-MM-DD). Padrão: 1980-01-01. (Ou data_inicio ou data_ini.) |
data_final |
date | não | Último dia (AAAA-MM-DD). Padrão: 2099-12-31. (Ou data_fim.) |
id_tx_estabelecimento |
integer | não | Filtra a filial (0 = todas) |
id_cliente |
integer | não | Filtra o cliente (0 = todos) |
id_produto |
integer | não | Filtra o produto (0 = todos) (Ou id_comb.) |
page |
integer | não | Página (padrão 1). |
size |
integer | não | Itens por página, de 1 a 50 (padrão 50). |
curl -s -X GET "$BASE/v1/terceiro/movimentoSaldoDia?$AUTH"
Resposta:
{
"status": "ok",
"data": [
{
"id_cliente": 10,
"cliente": "DISTRIBUIDORA A",
"id_produto": 5,
"produto": "ETANOL",
"dia": "2026-11-10",
"saldo_ant_fisico": 100000.0,
"saldo_ant_fiscal": 100500.0,
"saldo_ant_dif": 500.0,
"entrada_fisico": 30000.0,
"entrada_fiscal": 30000.0,
"entrada_dif": 0.0,
"saida_fisico": 20000.0,
"saida_fiscal": 20100.0,
"saida_dif": 100.0,
"saldo_fisico": 110000.0,
"saldo_fiscal": 110400.0,
"saldo_dif": 400.0
}
],
"param": {
"_count": 1,
"_pages": 1,
"_size": 50,
"_page": 1
}
}
Erros específicos: 403 — {"errors":{"acesso":"Negado"}}: fora do escopo do acesso..