---
title: "Como exportar NFS-e em massa (XML, PDF, CSV)"
description: "Receita para gerar arquivos consolidados (XML, PDF ou CSV analítico) de NFS-e capturadas em lote, via API assíncrona do shared-usage-api da NFE.io."
source_url: https://nfe.io/docs/distribuicao-nfse-inbound-bulk-export/
last_updated: 2026-07-30
---

# Como exportar NFS-e em massa (XML, PDF, CSV)

Em vez de baixar XML/PDF nota a nota, gere **um único arquivo consolidado** com todas as NFS-es de um período. Casos típicos: fechamento contábil mensal, conciliação com contas a pagar, geração de relatórios para Power BI, auditoria SEFAZ. A geração roda no `shared-usage-api` (pipeline separado do `dfetech-distribution-api`), de forma assíncrona, e entrega o resultado via URL temporária por e-mail.

## Sumário

- [Pré-requisitos](#pré-requisitos)
- [Fluxo](#fluxo)
- [Solução](#solução)
- [Variações](#variações)
- [Armadilhas comuns](#armadilhas-comuns)

## Pré-requisitos

- Empresa com NFS-e Inbound ativo e documentos capturados — veja [Integração REST](./integracao-rest.md).
- API Key com papel `Nota Fiscal (api.nfe.io)` ou `NFSeDist (dfe.nfe.io)` — a mesma usada na API principal.
- `accountId` e `subscriptionId` da sua conta — visíveis no painel NFE.io.
- Cliente HTTP capaz de polling (cURL + jq, Python, Node, etc.).

## Fluxo

```mermaid
flowchart LR
    A[Request POST exports] --> B[Queue shared-usage-api]
    B --> C[Worker gera ZIP/CSV em blob]
    C --> D[Signed URL com TTL 7d]
    D --> E[Cliente faz polling GET status]
    E --> F[Download via downloadUrl]
```

## Solução

A exportação é **assíncrona**: você cria um `ExportJob` via `POST` (resposta `202 Accepted`), recebe um `jobId`, e acompanha por polling em `GET .../exports({jobId})` até `status: "Completed"`. O resultado fica em uma URL pré-assinada (HMAC) válida por **7 dias** — baixe ou encaminhe rápido.

Três formatos de saída via `resource`:

| `resource` | Saída | Tempo típico (1.000 notas) |
|---|---|---|
| `company-nfse-inbound-xml` | ZIP de XMLs assinados | 3-8 minutos |
| `company-nfse-inbound-pdf` | ZIP de DANFSes em PDF | 3-8 minutos |
| `company-nfse-inbound-analytical-csv` | CSV analítico com 24 colunas (1 linha por nota) | 30-60 segundos |

### Etapa 1: Criar o job de exportação

```bash
export NFEIO_API_KEY="<sua-chave>"
export ACCOUNT_ID="<account-id>"
export SUB_ID="<subscription-id>"
export USAGE_BASE="https://shared-usage-api.azurewebsites.net"

curl -X POST "$USAGE_BASE/accounts($ACCOUNT_ID)/subscriptions($SUB_ID)/exports" \
  -H "Authorization: $NFEIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "companyId": "65a1b2c3d4e5f6789abcdef0",
    "resource": "company-nfse-inbound-analytical-csv",
    "beginOn": "2026-04-01",
    "endOn": "2026-04-30",
    "emails": ["fiscal@minhaempresa.com.br"],
    "createdBy": "fiscal@minhaempresa.com.br",
    "userEmail": "fiscal@minhaempresa.com.br",
    "apiKey": "'$NFEIO_API_KEY'",
    "splitDays": false,
    "language": "pt-BR"
  }'
```

Resposta `202 Accepted` traz `id` (= `jobId`) e `status: "Pending"`. O header `Location` aponta para o endpoint de acompanhamento.

### Etapa 2: Acompanhar até concluir

```bash
JOB_ID="<id-retornado>"

while true; do
  RESP=$(curl -s "$USAGE_BASE/accounts($ACCOUNT_ID)/subscriptions($SUB_ID)/exports($JOB_ID)" \
    -H "Authorization: $NFEIO_API_KEY")
  STATUS=$(echo "$RESP" | jq -r .status)
  echo "Status: $STATUS"
  [ "$STATUS" = "Completed" ] && break
  [ "$STATUS" = "Failed" ] && echo "ERRO: $(echo $RESP | jq -r .errorMessage)" && exit 1
  sleep 30
done

DOWNLOAD_URL=$(echo "$RESP" | jq -r .downloadUrl)
curl -o nfse-inbound-202604.csv "$DOWNLOAD_URL"
```

Estados terminais: `Completed` (sucesso, `downloadUrl` válida por 7 dias), `Failed` (`errorMessage` preenchido). Os contadores `totalLines` (notas no arquivo final) e `failed` (notas que erraram individualmente sem parar o job) ajudam a validar — se `failed > 0`, abra os detalhes para investigar.

### Etapa 3: Interpretar o CSV analítico

Cada linha = 1 NFS-e. As **24 colunas** combinam identificação (`Invoice_Id`, `NSU`, `Access_Key`), datas (`Generated_On`, `Issued_Date`, `Accrual_On`, `Created_At`), partes (`Provider_Federal_Tax_Number`, `Borrower_Federal_Tax_Number` e nomes), valores (`Services_Amount`), classificação (`Issue_City_Code`, `Service_Code`), status (`Invoice_Status`, `Webhook_Status`, `Has_Pdf`, `Environment`, `Description`) e — para notas com eventos relacionados — o **evento primário achatado**: `Event_Type`, `Event_Code`, `Event_Access_Key`, `Event_Generated_On`, `Substitute_Access_Key`.

A regra de prioridade do evento primário (NFS-e): **Substituição** (`310611`) > **Cancelamento** (`310610`) > mais recente por `GeneratedOn`. Quando a nota não tem evento, as 5 colunas finais ficam vazias mas a linha continua sendo emitida.

Encoding: ISO-8859-1, delimitador `;`, CRLF, decimais com ponto. Abre direto no Excel BR sem conversão.

> ⚠️ Os códigos `310610`/`310611` que aparecem na coluna `Event_Code` deste CSV são do **catálogo NFE.io**, não os códigos XSD `tpEvento` do SEFIN. Veja [Códigos de evento](../reference/codigos-evento.md) para o mapeamento.

## Variações

- **`splitDays=true`**: gera **1 arquivo por dia** em vez de um único. Recomendado para períodos longos (>1 mês) — facilita download paralelo e tolerância a falha por dia.
- **`language: "en-US"`**: colunas do CSV em inglês. Útil para sistemas internacionais ou times multilíngues.
- **NF-e Recebidas em massa**: o mesmo endpoint aceita os `resource` paralelos `company-nfe-inbound-{xml,pdf,analytical-csv}`. CT-e Recebidas **não tem bulk export** ainda (no roadmap).
- **Sem e-mail (polling-only)**: envie `emails: []`. Útil para integrações automatizadas.
- **Reexecução de período**: simplesmente crie um novo job com o mesmo `beginOn`/`endOn`. Não há endpoint de "atualizar job".

## Armadilhas comuns

- **`apiKey` no body é obrigatório**: o worker do `shared-usage-api` é assíncrono e não tem acesso ao header `Authorization` original — precisa do valor duplicado no body. Sem ele, `400 MISSING_API_KEY`.
- **`createdBy`/`userEmail` aparecem em logs de auditoria**: use um identificador rastreável (e-mail real do solicitante), não valores genéricos como `system` ou `bot`.
- **`downloadUrl` expira em 7 dias**: por política de privacidade, o arquivo é deletado após esse prazo. Baixe e armazene localmente se precisar reter — não guarde só o link.
- **Polling agressivo não acelera**: intervalo de 30 segundos é suficiente. Polling mais frequente desperdiça quota e não muda o tempo de processamento (que depende do volume de notas e da fila do `AzExport`).
- **Job "Em processamento" por mais de 1 hora**: pode estar travado. Verifique status persistente; se continuar, contate o suporte mencionando o `jobId`.
- **CSV abre tudo em 1 coluna no Excel**: o Excel está usando delimitador errado. Importe via **Dados → Obter Dados → Do Arquivo → CSV/Texto**, escolha delimitador `;` e encoding ISO-8859-1.
- **Excede limite de período**: máximo prático é 6 meses. Para fechamento anual, use `splitDays=true` ou rode 12 jobs mensais.

## Veja também

- [Integração REST](./integracao-rest.md) — consumo individual de documentos via API principal
- [Catálogo de eventos do webhook](../reference/webhook-events.md) — captura em tempo real (alternativa a bulk para fluxo contínuo)
- [Códigos de evento](../reference/codigos-evento.md) — mapeamento entre `Event_Code` do CSV e `tpEvento` do XSD
- [Arquitetura](../explanation/arquitetura.md) — como `shared-usage-api` se relaciona com a API principal
- [Troubleshooting](../reference/troubleshooting.md) — diagnóstico de jobs `Failed`
