API NotaGuard 1.7.0
Esta página monta a referência interativa no navegador. O guia completo e o contrato OpenAPI, que é a mesma fonte usada aqui, estão em notaguard.com.br/api/openapi.json.
Rotas
GET /v1/me: Dados da chave e da empresaGET /v1/notas: Listar notasGET /v1/notas/resumo: Totais agregadosGET /v1/notas/{id}: Detalhe de uma notaGET /v1/notas/{id}/itens: Itens da notaGET /v1/notas/{id}/eventos: Eventos SEFAZ da notaGET /v1/etiquetas: Etiquetas da empresaGET /v1/notas/{id}/xml: XML autorizadoGET /v1/notas/{id}/pdf: PDF do documento (DANFE ou DANFSe)POST /v1/notas/exportacoes: Criar exportação em loteGET /v1/notas/exportacoes: Listar exportaçõesGET /v1/notas/exportacoes/{id}: Status de uma exportação
Guia
Interface HTTP de leitura dos documentos fiscais que o NotaGuard monitora para a
sua empresa. Permite listar NF-e, NFC-e e NFS-e, consultar um documento
específico (com tributos, referências, etiquetas e parcelas de pagamento),
listar itens e eventos SEFAZ, baixar o XML autorizado e gerar o PDF de
representação (DANFE ou DANFSe).
## Visão geral
| | |
| --- | --- |
| URL base | `https://api.notaguard.com.br` |
| Versão | `v1` |
| Autenticação | Bearer token no header `Authorization`, uma chave por empresa |
| Métodos | Somente leitura. `GET`, com uma exceção: `POST /v1/notas/exportacoes` cria uma exportação em lote |
| Formato | JSON. Datas em ISO 8601, sempre UTC |
| Paginação | Por cursor. Não há parâmetro de offset |
| Limite de uso | 60 unidades de custo por minuto, por chave |
| CORS | Não habilitado. As chamadas devem partir do seu servidor |
A especificação completa está em
[openapi.json](https://notaguard.com.br/api/openapi.json), pronta para importar
em Postman, Insomnia ou gerador de cliente, e para ser lida por ferramentas
automatizadas.
## Autenticação
Toda requisição exige uma chave de API no header:
```
Authorization: Bearer ng_live_sua_chave_aqui
```
As chaves são criadas em **Configurações > Integrações > API** no painel, por
proprietários e administradores da empresa. Cada chave dá acesso aos documentos de uma única
empresa, e o token completo é exibido apenas no momento da criação: depois disso,
só o prefixo fica visível. Se o token for perdido, revogue a chave e crie outra.
A API não envia headers de CORS de propósito: ela é feita para ser chamada do seu
servidor. Chamar do navegador exporia sua chave no bundle JavaScript.
## Primeira chamada
`GET /v1/me` valida a chave e devolve a empresa que ela abre, os escopos
concedidos e o limite restante na janela atual. É a forma mais rápida de
confirmar que a integração está configurada corretamente.
```bash
curl https://api.notaguard.com.br/v1/me \
-H "Authorization: Bearer ng_live_sua_chave_aqui"
```
Para listar documentos, use `GET /v1/notas`:
```bash
curl "https://api.notaguard.com.br/v1/notas?tipo=NFe&limite=50" \
-H "Authorization: Bearer ng_live_sua_chave_aqui"
```
## Detalhe: id ou chave de acesso, e blocos opcionais
Toda rota de documento (`/v1/notas/{id}`, `/xml`, `/pdf`, `/itens`,
`/eventos`) aceita no lugar de `{id}` tanto o `id` (UUID) devolvido na
listagem quanto a **chave de acesso** do documento. Se o seu sistema já tem a
chave, não precisa buscar o UUID antes:
```bash
curl "https://api.notaguard.com.br/v1/notas/35260112345678000195550010000000011123456782" \
-H "Authorization: Bearer ng_live_sua_chave_aqui"
```
O detalhe devolve mais do que a listagem (destinatário, natureza da operação,
protocolo de autorização, finalidade) e aceita blocos opcionais via `incluir`:
```bash
curl "https://api.notaguard.com.br/v1/notas/{id}?incluir=tributos,referencias,etiquetas,duplicatas,cfop" \
-H "Authorization: Bearer ng_live_sua_chave_aqui"
```
- `tributos`: ICMS, IPI, PIS/COFINS, ISS, retenções e IBS/CBS quando presentes.
- `referencias`: vínculos com outros documentos, nos dois sentidos: devolução,
nota referenciada (`NFref`), substituição de NFS-e e o CT-e que transportou a
mercadoria.
- `etiquetas`: as marcações aplicadas no painel do NotaGuard.
- `duplicatas`: parcelas de pagamento extraídas do XML, com a situação
acompanhada no contas a pagar.
- `cfop`: CFOPs distintos dos itens (NF-e e NFC-e). É uma lista porque uma
nota pode ter mais de um CFOP entre os itens.
Bloco não pedido não aparece na resposta, e cada bloco custa apenas a leitura
do que você pediu.
## CFOP
O CFOP é atributo do **item**, não da nota: uma NF-e pode misturar, por
exemplo, `5102` e `5405` nos itens. Por isso a API o expõe em três formas:
- `GET /v1/notas/{id}/itens` traz o CFOP de cada item.
- `incluir=cfop` (na listagem e no detalhe) adiciona ao documento a lista de
CFOPs distintos dos itens: `"cfop": ["5102", "5405"]`.
- `GET /v1/notas?cfop=5905,6905` filtra documentos com item em qualquer um
dos CFOPs. O filtro também vale em `/resumo` e na exportação em lote.
O CFOP vem dos itens do XML completo: documento só com resumo tem
`"cfop": null` no `incluir` e fica de fora do filtro. NFS-e não tem CFOP.
## Etiquetas
Etiquetas são marcadores que a sua equipe define e aplica nas notas pelo painel
(centro de custo, status de conferência, o que fizer sentido). Pela API:
- `GET /v1/etiquetas` lista as definições da empresa e os valores possíveis.
- `GET /v1/notas?etiqueta=centro-custo:matriz` filtra a listagem pelas notas
marcadas. `etiqueta=centro-custo` (sem valor) retorna as que têm a etiqueta
com qualquer valor.
- `incluir=etiquetas` no detalhe devolve as marcações da nota.
É a ponte entre a triagem manual feita no painel e o seu sistema: por exemplo,
o ERP importa somente as notas que alguém marcou como "aprovada".
## Paginação
A paginação é por cursor. Chame `GET /v1/notas`, use o `proximo_cursor` da
resposta na chamada seguinte, e pare quando `tem_mais` for `false`. Não existe
parâmetro de offset: offset duplica itens quando um documento novo chega entre
duas páginas.
A ordenação padrão é por `criada_em` decrescente (quando o documento entrou no
NotaGuard), campo que nunca é nulo e por isso dá paginação estável.
## Filtros de data: o dia é o dia inteiro, em horário de Brasília
Todo filtro de data aceita duas formas, e elas significam coisas diferentes:
- **Data pura** (`AAAA-MM-DD`) recorta o **dia civil completo no fuso de
Brasília** (America/São Paulo). `data_ref_de=2026-07-01&data_ref_ate=2026-07-31`
pega de 1º de julho 00:00 até 31 de julho 23:59:59, como o painel mostra. É a
forma recomendada para fechamento de período.
- **Instante ISO 8601 completo** (`2026-07-31T18:00:00Z`) é usado exatamente
como veio, sem arredondar. Use quando você precisa de um corte por hora.
Isso vale nos dois extremos: o `_de` não puxa notas da noite do dia anterior, e
o `_ate` não descarta as do último dia. As respostas continuam em UTC.
## Sincronização incremental
Para manter uma cópia atualizada sem varrer tudo a cada execução, guarde o maior
`atualizada_em` que você recebeu e passe em `data_atualizacao_apos` na próxima vez.
Aqui prefira o instante ISO completo, e não a data pura: você quer continuar
exatamente de onde parou, não do início do dia.
## Documentos que só têm resumo
Uma parte grande do acervo aparece com `status: "resumida"`, sem `valor` nem
`data_emissao` e com `xml_completo_disponivel: false`. Existem **duas
situações bem diferentes** por trás disso, e confundi-las leva a conclusões
erradas sobre "notas faltando":
**1. Nota que a sua empresa recebeu** (`vinculo: "receptor"`). A SEFAZ entrega
primeiro um resumo e, em seguida, o documento completo, que sobrescreve o
resumo automaticamente. Na prática isso acontece em segundos e o estado
`resumida` é transitório: no acervo atual, praticamente toda nota recebida já
está completa. Se um documento ficar parado nesse estado, o caminho é registrar
a **ciência da operação**, que é o que autoriza a SEFAZ a liberar o XML.
**2. Nota que a sua empresa emitiu** (`vinculo: "emissor"`). A SEFAZ não
devolve ao emissor, pela distribuição, o XML daquilo que ele mesmo emitiu. O
NotaGuard fica sabendo dessas notas de forma indireta, por eventos de terceiros
que as referenciam (por exemplo, o CT-e que transportou a mercadoria). Elas
permanecem sem valor e sem data indefinidamente, e isso **não** é atraso de
processamento: o dado não existe do lado de cá. Para tê-lo, envie o XML da sua
emissão pelo painel.
Por isso, ao sincronizar, filtre por `vinculo`: `?vinculo=receptor` devolve o
acervo recebido, que é o que vem completo.
Em qualquer um dos casos, `GET /v1/notas/{id}/xml` continua funcionando e
devolve o XML de resumo (nome do arquivo terminando em `-resumo.xml`). Só o
PDF exige o XML completo.
### Como o XML completo é liberado (manifestação do destinatário)
Isto não é uma regra do NotaGuard, é da SEFAZ, e costuma ser a explicação real
para "a nota está lá mas o XML não vem".
Na distribuição de DF-e, a SEFAZ entrega ao destinatário **primeiro o resumo**
(`resNFe`: chave, emissor, valor e data). O documento **completo** (`procNFe`,
com itens, tributos e cobrança) só é liberado depois que o destinatário
**manifesta** a operação. A manifestação é um evento registrado na SEFAZ, e para
este efeito valem:
- **Ciência da operação** (`210210`) — "recebi o documento e ainda estou
apurando". É o passo mínimo que libera o XML completo, e o mais usado.
- **Confirmação da operação** (`210200`) — confirma que a operação de fato
ocorreu. Também libera o XML.
- **Desconhecimento** (`210220`) e **operação não realizada** (`210240`)
registram o oposto e não servem para "destravar" o download.
Depois da manifestação, o documento completo entra na fila de distribuição e é
capturado no ciclo seguinte de consulta: **não é instantâneo**. Enquanto isso, a
nota continua com `status: "resumida"` e `xml_completo_disponivel: false`, e
`/pdf` responde `409 xml_indisponivel`.
**No NotaGuard isso pode ser automático.** Em **Configurações > Gerais** existe
a opção **Ciência Automática**: com ela ligada, o NotaGuard registra a ciência
das notas recebidas assim que elas aparecem, sem ninguém precisar clicar, e o
XML completo passa a chegar sozinho. Se a sua integração encontra muitos
documentos em `resumida`, verifique essa opção antes de tratar como falha da
API: provavelmente as notas estão só esperando manifestação.
Manifestação **não se aplica** a nota que a sua própria empresa emitiu (caso 2
acima) nem a NFS-e; nesses casos o caminho é enviar o XML pelo painel.
Nulo aqui significa **desconhecido**, não zero. Trate esse caso explicitamente:
somar `valor` sem checar produz total subestimado. O endpoint
`/v1/notas/resumo` devolve `total_sem_valor` para você medir esse efeito.
Situações possíveis em `status`:
- `autorizada`: Documento autorizado, com XML completo disponível.
- `resumida`: Só existe o **resumo** do documento, sem o XML completo: `valor` e `data_emissao` geralmente vêm `null` e `xml_completo_disponivel` é `false` (o XML de resumo continua disponível para download). Em nota recebida é um estado transitório, que dura até o documento completo chegar; em nota emitida pela sua empresa é permanente, porque a SEFAZ não devolve pela distribuição o XML da própria emissão. Veja a seção "Documentos que só têm resumo".
- `cancelada`: Documento cancelado na SEFAZ.
- `denegada`: Emissão denegada pela SEFAZ.
- `desconhecido`: A SEFAZ não informou situação reconhecível para o documento.
## Exportação em lote (XML e PDF)
Para baixar muitos documentos de uma vez, use `POST /v1/notas/exportacoes` em
vez de iterar nos endpoints unitários: além de mais barato no limite de uso, é
uma requisição em vez de centenas. O resultado é sempre um ZIP com os arquivos
nomeados pela chave de acesso e um `manifesto.csv` dizendo, documento a
documento, o que entrou e o que não entrou (e por quê).
A seleção dos documentos usa **os mesmos filtros da listagem** (campo
`filtros`) ou uma lista explícita (campo `ids`). Ao usar `filtros`, um
**período fechado é obrigatório**: `data_ref_de`+`data_ref_ate` (recomendado;
é a data de referência do painel: emissão em NF-e/NFC-e, competência em NFS-e),
`data_emissao_de`+`data_emissao_ate` ou `data_criacao_de`+`data_criacao_ate`.
Exportação sem recorte de tempo não existe de propósito: "o acervo inteiro" não
é um pedido de exportação, é sincronização, e para isso o caminho é
`data_atualizacao_apos` na listagem. Existem duas entregas, e **você** escolhe
qual quer:
**Entrega `direta`** (síncrona): para até 50
documentos, somente XML. O ZIP vem no corpo da resposta, sem espera:
```bash
curl -X POST https://api.notaguard.com.br/v1/notas/exportacoes \
-H "Authorization: Bearer ng_live_sua_chave_aqui" \
-H "Content-Type: application/json" \
-d '{"formatos": ["xml"], "entrega": "direta", "filtros": {"data_ref_de": "2026-07-01", "data_ref_ate": "2026-07-31"}}' \
-o notas.zip
```
**Entrega `arquivo`** (assíncrona, o padrão): para lotes maiores e para
qualquer lote com PDF. A resposta é `202` com um job; consulte o status até
`concluida` e baixe pelo campo `url`:
```bash
curl -X POST https://api.notaguard.com.br/v1/notas/exportacoes \
-H "Authorization: Bearer ng_live_sua_chave_aqui" \
-H "Content-Type: application/json" \
-d '{"formatos": ["xml", "pdf"], "filtros": {"data_ref_de": "2026-07-01", "data_ref_ate": "2026-07-31", "vinculo": "receptor"}}'
# resposta: 202 { "id": "...", "status": "pendente", "total_documentos": 480, ... }
curl https://api.notaguard.com.br/v1/notas/exportacoes/{id} \
-H "Authorization: Bearer ng_live_sua_chave_aqui"
# repita até "status": "concluida"; então baixe o ZIP pelo campo "url"
```
Regras que valem a pena conhecer antes de integrar:
- **Faça polling com calma.** Enquanto `pendente`/`processando`, a resposta
traz `Retry-After: 5`. Lotes pequenos concluem em segundos; um lote grande
de PDFs pode levar alguns minutos.
- **Limites por exportação**: 5000 documentos quando só XML,
500 quando inclui PDF (gerar PDF custa ~1s por
documento). Pedido acima do limite responde `422` **com a contagem real**,
para você saber exatamente como dividir. Limites ajustáveis por empresa, como
o limite de requisições.
- **Uma exportação ativa por vez** por empresa (`409` na segunda). Repetir o
MESMO pedido não dá erro: devolve o job já em andamento. Até
20 exportações por período de 24h.
- **O link de `url` vale 1 hora**; expirou, consulte o job de novo e receba
outro. **O arquivo vale 48 horas**; depois disso o status vira `expirada` e
é preciso exportar de novo.
- **Sucesso parcial**: documento sem XML completo não derruba o lote. Ele entra
no `manifesto.csv` com o motivo (`sem_xml_completo`, por exemplo) e nos
contadores `incluidos_xml` / `incluidos_pdf` / `falhas` do job. XML de
**resumo** entra no ZIP com o sufixo `-resumo.xml`, como no endpoint
unitário.
- **Exportação é para fechar período** (o mês do contador, uma auditoria), não
para sincronização contínua. Para manter seu sistema atualizado, use
`data_atualizacao_apos` na listagem, que é incremental e muito mais barato.
## Limites de uso
Cada chave tem um custo permitido por minuto (padrão 60). Endpoints mais caros
consomem mais de uma unidade:
| Endpoint | Custo |
| --- | --- |
| `/v1/me`, `/v1/notas`, `/v1/notas/resumo`, `/v1/notas/{id}`, `/v1/notas/{id}/itens`, `/v1/notas/{id}/eventos`, `/v1/etiquetas` | 1 |
| `GET /v1/notas/exportacoes`, `GET /v1/notas/exportacoes/{id}` | 1 |
| `/v1/notas/{id}/xml` | 2 |
| `/v1/notas/{id}/pdf` | 10 |
| `POST /v1/notas/exportacoes` com entrega `direta` | 10 |
| `POST /v1/notas/exportacoes` com entrega `arquivo` | 20 |
Repare que o lote é muito mais barato que o equivalente unitário: 50
XMLs pela entrega direta custam 10 unidades, contra 100 baixando um a um. Se a
sua integração busca vários arquivos, o lote é o caminho certo.
**Requisição que falha antes do trabalho pesado custa 1 unidade, não o preço
cheio.** Um `/pdf` que responde `404` ou `409 xml_indisponivel` consome 1, não
10, porque nenhuma geração começou. O preço cheio só é cobrado quando o arquivo
realmente vai ser produzido ou baixado.
Ainda assim, o jeito certo de varrer o acervo é filtrar antes:
`GET /v1/notas?xml_completo_disponivel=true` devolve só os documentos que
conseguem gerar PDF, em vez de descobrir isso um a um.
Acompanhe pelos headers `X-RateLimit-Limit`, `X-RateLimit-Remaining` e
`X-RateLimit-Reset`. Ao receber `429`, respeite o `Retry-After`.
> **Precisa de um limite maior?** O limite é ajustável por empresa e não depende
> de mudança no seu código nem de troca de chave.
> [Fale com o suporte](https://notaguard.com.br/suporte) informando o volume que
> a sua integração precisa.
## Erros
Toda resposta de erro tem o mesmo formato, com um `codigo` estável e um
`id_requisicao` para o suporte:
```json
{
"erro": {
"codigo": "parametro_invalido",
"mensagem": "tipo inválido: 'nfe'. Valores aceitos: NFe, NFCe, NFSe.",
"id_requisicao": "req_01JQ8Z2K9M"
}
}
```
- `nao_autorizado`: Header `Authorization` ausente ou malformado.
- `token_invalido`: O token não corresponde a nenhuma chave ativa.
- `token_revogado`: A chave foi revogada no painel.
- `token_expirado`: A chave passou da data de expiração.
- `ip_nao_autorizado`: A chave tem lista de IPs permitidos e a requisição veio de outro IP.
- `escopo_insuficiente`: A chave não tem o escopo exigido por este endpoint.
- `recurso_nao_disponivel_no_plano`: O plano da empresa não inclui acesso via API.
- `nao_encontrado`: Documento inexistente ou pertencente a outra empresa. A API não diferencia os dois casos de propósito, para não permitir descoberta de documentos de terceiros. **Só isso**: quando o documento existe mas o arquivo pedido ainda não, o código é `xml_indisponivel`.
- `xml_indisponivel`: O documento existe, mas o XML necessário para atender a requisição ainda não chegou da SEFAZ. Em `/pdf` significa que só há o resumo (o PDF exige o XML completo); em `/xml`, que não há nem o completo nem o resumo. **Não é permanente em nota recebida**: o XML completo é liberado pela SEFAZ após a manifestação do destinatário. Veja "Documentos que só têm resumo" e não trate como erro definitivo antes de checar `xml_completo_disponivel` na listagem.
- `parametro_invalido`: Algum parâmetro da query é inválido ou desconhecido. A mensagem indica qual é e quais valores são aceitos.
- `cursor_invalido`: O cursor de paginação está corrompido ou não foi gerado por esta API.
- `limite_de_requisicoes_excedido`: Limite de requisições por minuto excedido. Respeite o header `Retry-After`.
- `metodo_nao_permitido`: A API v1 é somente leitura: apenas `GET` é aceito.
- `nao_disponivel_para_este_tipo`: O recurso existe, mas não se aplica a este tipo de documento. Hoje acontece na lista de itens de NFS-e: serviço não tem itens, a descrição está em `descricao_servico`, no detalhe da nota.
- `exportacao_em_andamento`: Já existe uma exportação pendente ou em processamento para esta empresa (uma por vez). A mensagem traz o `id` dela: acompanhe por `GET /v1/notas/exportacoes/{id}` e crie a próxima quando concluir. Repetir o MESMO pedido não dá este erro: devolve o job existente.
- `exportacao_acima_do_limite`: O pedido casa com mais documentos do que o limite permite. A mensagem traz a contagem real e o limite: restrinja os filtros (por exemplo, um período menor) ou divida em mais de uma exportação. Na entrega `direta`, acima do limite o caminho é usar a entrega `arquivo`.
- `exportacao_sem_documentos`: Nenhum documento casa com os filtros ou ids informados.
- `limite_diario_de_exportacoes`: Limite de exportações nas últimas 24 horas atingido. O limite é ajustável por empresa: fale com o suporte se o seu volume precisar de mais.
- `erro_interno`: Falha inesperada. O `id_requisicao` identifica a ocorrência no suporte.
Códigos publicados são estáveis: dentro de `/v1` nunca são renomeados nem
removidos.