Consultar NF-e por chave
Baixe o XML completo e assinado (nfeProc) da NF-e por chave de acesso usando o certificado digital do cliente, sem custódia.
POST /api/consultar-nfe-xml
Retorna o XML completo (nfeProc assinado) de uma NF-e a partir da chave de acesso de 44 dígitos, usando o certificado digital do cliente (e-CPF ou e-CNPJ A1) enviado na requisição. Uma chave por requisição.
O certificado não é armazenado (zero custódia): ele é usado apenas no momento da consulta e descartado em seguida. Só é retornada a nota quando o titular do certificado é participante (emitente, destinatário, transportador ou autorizado no XML).
Cobrança: 3 créditos quando a chave retorna XML. Sem retorno (não encontrada, fora do prazo, erro) não cobra. Em R$ por nota, pela franquia de cada plano: Lite R$ 2,00 · Starter R$ 0,30 · Pro R$ 0,195 · Enterprise R$ 0,075. Contas com preço negociado (exclusivo) debitam 1 crédito por nota.
Para consultar várias notas, faça uma requisição por chave (em paralelo ou sequencial). A resposta mantém o envelope com resultados[] contendo um item.
Autenticação
Envie sua chave no header X-API-Key. Veja Autenticação para detalhes.
Corpo da requisição
Envie um JSON (Content-Type: application/json) com os campos abaixo.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
chave | string | Sim | Chave de acesso de 44 dígitos (uma por requisição). Espaços e pontos são ignorados. |
certificado | string | Sim | Arquivo do certificado A1 (.pfx/.p12) codificado em base64. |
senha | string | Sim | Senha do certificado. |
manifestar | boolean | Não | Padrão true. Quando a SEFAZ devolve só o resumo (destinatário sem manifestação), registra a manifestação do destinatário com este certificado para liberar o XML (veja "Ciência da Operação automática"). false devolve somente_resumo sem registrar nenhum evento. |
O titular do certificado precisa ser participante da nota. Notas mais antigas podem não ser mais disponibilizadas pela consulta por chave da SEFAZ (cStat 632) — nesses casos a FiscalAPI tenta automáticamente o portal da NF-e com o mesmo certificado, ampliando o alcance para notas antigas. O certificado e a senha nunca são gravados.
Exemplos de código
# codifica o certificado em base64 e envia
CERT=$(base64 -w0 certificado.pfx)
curl -X POST "https://api.fiscalapi.com.br/api/consultar-nfe-xml" \
-H "X-API-Key: fapi_sua_chave_aqui" \
-H "Content-Type: application/json" \
-d "{\"chave\":\"43260689677595000128550030006074891411409127\",\"certificado\":\"$CERT\",\"senha\":\"sua-senha\"}"import { readFileSync } from "node:fs";
const certificado = readFileSync("certificado.pfx").toString("base64");
const response = await fetch(
"https://api.fiscalapi.com.br/api/consultar-nfe-xml",
{
method: "POST",
headers: {
"X-API-Key": "fapi_sua_chave_aqui",
"Content-Type": "application/json",
},
body: JSON.stringify({
chave: "43260689677595000128550030006074891411409127",
certificado,
senha: "sua-senha",
}),
}
);
const data = await response.json();
console.log(data.resultados[0]);import base64
import requests
with open("certificado.pfx", "rb") as f:
certificado = base64.b64encode(f.read()).decode()
response = requests.post(
"https://api.fiscalapi.com.br/api/consultar-nfe-xml",
headers={"X-API-Key": "fapi_sua_chave_aqui"},
json={
"chave": "43260689677595000128550030006074891411409127",
"certificado": certificado,
"senha": "sua-senha",
},
)
data = response.json()
print(data["resultados"][0])$certificado = base64_encode(file_get_contents('certificado.pfx'));
$response = Http::withHeaders([
'X-API-Key' => 'fapi_sua_chave_aqui',
])->post('https://api.fiscalapi.com.br/api/consultar-nfe-xml', [
'chave' => '43260689677595000128550030006074891411409127',
'certificado' => $certificado,
'senha' => 'sua-senha',
]);
$data = $response->json();var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "fapi_sua_chave_aqui");
var certificado = Convert.ToBase64String(File.ReadAllBytes("certificado.pfx"));
var payload = new
{
chave = "43260689677595000128550030006074891411409127",
certificado,
senha = "sua-senha",
};
var content = new StringContent(
System.Text.Json.JsonSerializer.Serialize(payload),
System.Text.Encoding.UTF8,
"application/json"
);
var response = await client.PostAsync(
"https://api.fiscalapi.com.br/api/consultar-nfe-xml", content
);
var data = await response.Content.ReadAsStringAsync();Resposta
Campos de nível superior
| Campo | Tipo | Descrição |
|---|---|---|
request_id | string | Identificador único da requisição (UUID). |
total | integer | Sempre 1 (uma chave por requisição). |
com_dado | integer | 1 se a chave retornou XML, senao 0. |
creditos_cobrados | integer | Créditos cobrados (3 por chave que retornou XML). |
resultados | array | Lista com um resultado (a chave consultada). |
Campos de cada resultado (resultados[])
| Campo | Tipo | Descrição |
|---|---|---|
chave | string | Chave de acesso (44 dígitos). |
status | string | Resultado da chave. Veja a tabela de status. |
cstat | string | Código de status retornado pela SEFAZ (ex: 138, 632). |
mensagem | string | Descrição legível do resultado. |
from_cache | boolean | Indica se o XML veio do cache. |
manifestacao | string | null | Evento de manifestação registrado com o certificado nesta consulta (veja abaixo). null quando nenhum evento foi enviado. |
xml | string | null | XML completo (nfeProc) quando status = ok; caso contrário null. |
Valores de status
| Status | Significado | Cobra crédito |
|---|---|---|
ok | XML completo retornado em xml. | Sim |
somente_resumo | Só o resumo está disponível: o destinatário ainda não se manifestou e a Ciência da Operação não pode ser registrada (prazo de 10 dias vencido ou rejeição da SEFAZ). Veja "Ciência da Operação automática". | Não |
nao_autorizado | O titular do certificado não é participante da nota. | Não |
nao_encontrado | A SEFAZ não localizou a NF-e para esta chave/certificado. | Não |
fora_prazo | A SEFAZ não disponibiliza esta nota pela consulta por chave (cStat 632, típico de notas mais antigas). A FiscalAPI tenta o portal da NF-e automáticamente. | Não |
chave_invalida | Chave de acesso inválida. | Não |
erro | Falha na consulta (rejeição da SEFAZ, indisponibilidade, etc.). | Não |
Ciência da Operação automática
Os eventos abaixo são registrados na SEFAZ em nome do titular do certificado e não podem ser desfeitos pela FiscalAPI. Ao consultar com manifestar ativo (padrão), você autoriza esses registros, conforme a seção 2.1 dos Termos de Uso. Para receber apenas o resumo sem registrar nada, envie manifestar: false.
Quando o certificado é do destinatário e ele ainda não se manifestou, a SEFAZ devolve apenas o resumo da nota. Nesse caso a FiscalAPI registra a Ciência da Operação (evento 210210) com o próprio certificado e consulta de novo, entregando o XML completo na mesma requisição. O evento é assinado com o certificado enviado e fica registrado na SEFAZ em nome do destinatário.
A Ciência da Operação só é aceita pela SEFAZ em até 10 dias da autorização da NF-e (cStat 596). Passado esse prazo, a FiscalAPI segue nesta ordem:
- Portal da NF-e: tenta o download do XML pelo portal nacional com o mesmo
certificado. Não registra nenhum evento. Se o portal estiver indisponível
no momento (falha transitória), a consulta volta
somente_resumoe pede nova tentativa — nenhum evento é registrado nesse caso. - Confirmação da Operação (evento 210200, aceito em até 180 dias): se o portal respondeu e não liberou o download, a FiscalAPI registra a Confirmação com o certificado do destinatário e consulta de novo. A Confirmação declara que a operação ocorreu e impede o emitente de cancelar a NF-e. Ela só é enviada quando a Ciência foi recusada por prazo (ou a nota já tem mais de dois meses), nunca em outro tipo de rejeição.
Se a SEFAZ estiver limitando as consultas do certificado (cStat 656, "consumo indevido"), a manifestação é registrada normalmente e o XML é buscado pelo portal, que não tem esse limite.
O campo manifestacao informa o que aconteceu:
| Valor | Significado |
|---|---|
ciencia_registrada | Ciência da Operação registrada nesta consulta (cStat 135/136). |
ciencia_ja_registrada | A Ciência já constava na SEFAZ (cStat 573). |
ciencia_fora_prazo | Prazo de 10 dias vencido (cStat 596). Se status = ok, o XML veio do portal sem registrar evento. |
ciencia_rejeitada | A SEFAZ rejeitou a Ciência por outro motivo; o cstat e o motivo vêm em mensagem. |
ciencia_erro | Falha de comunicação ao registrar a Ciência; consulte novamente. |
confirmacao_registrada | Confirmação da Operação registrada nesta consulta (cStat 135/136). |
confirmacao_ja_registrada | A Confirmação já constava na SEFAZ (cStat 573). |
confirmacao_rejeitada | A SEFAZ rejeitou a Confirmação; o cstat e o motivo vêm em mensagem. |
confirmacao_erro | Falha de comunicação ao registrar a Confirmação; consulte novamente. |
ciencia_nao_suportada / confirmacao_nao_suportada | O certificado não tem chave RSA; a SEFAZ só aceita assinatura RSA-SHA1 em eventos. Nenhum evento é enviado. |
Registrar a Ciência da Operação não impede o destinatário de registrar depois Confirmação, Desconhecimento ou Operação não Realizada. A Confirmação da Operação é definitiva: depois dela não é possível registrar Desconhecimento.
Notas com mais de 180 dias da autorização não aceitam mais nenhuma
manifestação: a consulta volta somente_resumo e nenhum evento é enviado. Nota
cancelada ou denegada também não recebe evento (status = cancelada ou
erro).
Exemplo de resposta
{
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"total": 1,
"com_dado": 1,
"creditos_cobrados": 3,
"resultados": [
{
"chave": "43260689677595000128550030006074891411409127",
"status": "ok",
"cstat": "138",
"mensagem": "Documento localizado.",
"from_cache": false,
"manifestacao": null,
"xml": "<nfeProc versao=\"4.00\" ...>...</nfeProc>"
}
]
}Códigos de erro
| Código | HTTP Status | Descrição |
|---|---|---|
PARAMETRO_AUSENTE | 400 | Chave de acesso não informada. |
CHAVE_INVALIDA | 400 | A chave de acesso não tem 44 dígitos. |
CERTIFICADO_INVALIDO | 400 | Certificado ausente, base64 inválido, senha incorreta ou certificado expirado. |
LIMITE_PLANO | 402 | Créditos insuficientes no plano. |
RATE_LIMIT | 429 | Limite de requisições excedido. Aguarde e tente novamente. |
ERRO_INTERNO | 500 | Erro interno no servidor. |
Esta pagina foi util?