---
title: "Fiscal Document Capture Architecture — NF-e, CT-e and NFS-e"
description: "Architecture design of NFE.io Fiscal Document Capture (DFe Inbound): components, integration with government environments, deployment, security and resilience for NF-e, CT-e and NFS-e Inbound."
source_url: https://nfe.io/docs/distribuicao-arquitetura-en/
last_updated: 2026-09-25
---

# Fiscal Document Capture (DFe Inbound) Architecture — NF-e, CT-e and NFS-e

| | |
|---|---|
| **Product** | NFE.io Fiscal Document Capture (`dfetech-distribution-api`) — NF-e Inbound, CT-e Inbound and NFS-e Inbound |
| **Document** | 1 of 3 — Architecture design |
| **Version** | 1.1 — 2026-09-24 |
| **Audience** | Customers, architecture teams, IT, information security and tax teams |
| **Related documents** | [2 of 3 — Processing flows](./02-processing-flows.md) · [3 of 3 — Processing details and polling-frequency rules](./03-processing-and-polling-rules.md) · [Versão em português](../01-arquitetura.md) |

## 1. Summary

NFE.io **Fiscal Document Capture** automatically receives the electronic fiscal documents that third parties issue against the customer's CNPJ (Brazilian company tax ID). It queries the national distribution environments run by the Brazilian tax authorities, stores the XML files, extracts the metadata, makes the files available through a REST API, and notifies the customer's system through webhooks.

The service is made up of three independent sub-products that share the same platform:

| Sub-product | Documents captured | Government source | Source protocol |
|---|---|---|---|
| **NF-e Inbound** | NF-e (model 55, goods invoice) and its events | NF-e National Environment — `NFeDistribuicaoDFe` web service | SOAP with mutual TLS |
| **CT-e Inbound** | CT-e (model 57, transport document) and its events | CT-e National Environment — `CTeDistribuicaoDFe` web service | SOAP with mutual TLS |
| **NFS-e Inbound** | National Standard NFS-e (service invoice), DPS and events | National Data Environment (ADN) of the National NFS-e System | REST with mutual TLS |

Each sub-product is enabled **per company (CNPJ)** and runs in isolation. A failure or outage in one government environment does not stop the others.

## 2. Architecture principles

1. **Separation by document type.** Each sub-product has its own capture process (worker), its own queues and its own consumption limits. A high NF-e volume does not compete for resources with NFS-e capture.
2. **Asynchronous, message-driven processing.** Capture, per-document processing and notification are separate stages connected by message queues. Any stage can be reprocessed without redoing the previous ones.
3. **NSU-based cursor.** Capture progress is driven by the **NSU** (Unique Sequential Number) that the national environment assigns to each document addressed to the CNPJ. The last processed NSU is stored per company, and the next query starts from it.
4. **Disciplined use of government services.** The routine-capture polling and waiting rules defined in the Technical Notes (Notas Técnicas) are implemented in the capture engine itself, together with automatic pauses and blocks in response to rejections and shutdowns. Document 3 has the details.
5. **Idempotency.** Every document has a deterministic identifier (company + access key, company + event identifier, or company + NSU). Reprocessing a document overwrites the existing record instead of duplicating it.
6. **Automatic gap recovery.** A daily routine checks the continuity of the NSU sequence and recovers, one by one, any document that was not persisted.
7. **End-to-end observability.** All components emit distributed tracing, metrics and structured logs, and expose health checks.

## 3. Overview (context diagram)

```mermaid
flowchart LR
    subgraph GOV["Government environments"]
        AN_NFE["NF-e National Environment<br/>NFeDistribuicaoDFe"]
        AN_EVT["NF-e Event Reception<br/>NFeRecepcaoEvento4"]
        AN_CTE["CT-e National Environment<br/>CTeDistribuicaoDFe"]
        ADN["National NFS-e System<br/>ADN and Sefin Nacional"]
    end

    subgraph NFEIO["NFE.io Platform — Fiscal Document Capture"]
        API["Fiscal Document Capture REST API"]
        WNFE["NF-e Inbound worker"]
        WCTE["CT-e Inbound worker"]
        WNFSE["NFS-e Inbound worker"]
        CAD["Companies and<br/>Digital Certificates service"]
        HOOK["Notification Platform<br/>Webhooks"]
    end

    CLI["Customer system<br/>ERP, TMS, Accounts Payable"]
    CON["app.nfe.io console"]

    WNFE -- "distNSU / consNSU / consChNFe" --> AN_NFE
    WNFE -- "Awareness of Operation and<br/>recipient manifestations" --> AN_EVT
    WCTE -- "distNSU / consNSU" --> AN_CTE
    WNFSE -- "GET DFe by NSU and<br/>taker manifestation" --> ADN
    API -- "on-demand capture<br/>by access key" --> ADN

    WNFE & WCTE & WNFSE -- "company A1 certificate" --> CAD
    WNFE & WCTE & WNFSE -- "document events" --> HOOK
    HOOK -- "POST webhook" --> CLI
    CLI -- "HTTPS + API key" --> API
    CON -- "HTTPS" --> API
```

## 4. Component view

```mermaid
flowchart TB
    subgraph EDGE["Edge"]
        GW["HTTPS gateway<br/>api.nfse.io"]
    end

    subgraph APP["Application layer — Kubernetes cluster"]
        API["Fiscal Document Capture REST API<br/>automatic horizontal scaling"]
        subgraph WORKERS["Capture workers"]
            WNFE["NF-e Inbound worker"]
            WCTE["CT-e Inbound worker"]
            WNFSE["NFS-e Inbound worker"]
        end
    end

    subgraph DATA["Data layer"]
        MQ[("Message broker<br/>RabbitMQ — per-product queues<br/>and error queues")]
        DB[("Document database<br/>MongoDB — metadata, cursors,<br/>settings and audit trail")]
        OBJ[("S3-compatible<br/>object storage — XML and PDF")]
        CACHE[("Redis-compatible<br/>distributed cache — locks,<br/>concurrency control and<br/>point-query limit")]
    end

    subgraph PLAT["NFE.io internal platform services"]
        CAD["Companies and Certificates"]
        HOOK["Notifications — Webhooks"]
        USO["Usage recording"]
        PDF["NFS-e PDF generation"]
        IDP["Identity and API keys"]
    end

    subgraph OBS["Observability"]
        OTEL["OpenTelemetry<br/>traces, metrics and logs"]
        HB["External heartbeat and<br/>availability monitor"]
    end

    GW --> API
    API --> MQ
    API --> DB
    API --> OBJ
    API --> CACHE
    MQ --> WNFE & WCTE & WNFSE
    WNFE & WCTE & WNFSE --> DB
    WNFE & WCTE & WNFSE --> OBJ
    WNFE & WCTE & WNFSE --> CACHE
    WNFE & WCTE & WNFSE --> CAD
    WNFE & WCTE & WNFSE --> HOOK
    WNFE & WCTE & WNFSE --> USO
    WNFSE --> PDF
    API --> IDP
    API & WNFE & WCTE & WNFSE -.-> OTEL
    WNFE & WCTE & WNFSE -.-> HB
```

### 4.1 Component responsibilities

| Component | Responsibility |
|---|---|
| **HTTPS gateway** | Terminates TLS and routes the public Fiscal Document Capture routes (`/v2/companies/...`) to the API. |
| **Fiscal Document Capture REST API** | Enables and disables capture per company, queries documents and events, serves XML, PDF and JSON, and accepts manifestation and reprocessing requests. Authenticates with API keys and authorizes by product profile. Runs on-demand NFS-e capture by access key. Scales horizontally based on CPU usage. |
| **NF-e Inbound worker** | Schedules and runs the `NFeDistribuicaoDFe` query, processes each NSU (summary, full NF-e, events), schedules the automatic Awareness of Operation for after the waiting time set by the company (the only manifestation sent automatically), sends manifestations to the event environment (the National Environment's `NFeRecepcaoEvento4`; Tax Reform events through the corresponding event environment), and runs the daily NSU reconciliation. |
| **CT-e Inbound worker** | Schedules and runs the `CTeDistribuicaoDFe` query, processes each NSU (CT-e and events), applies the event and interested-party filters, provides item and batch reprocessing and consolidation, and runs the daily NSU reconciliation. |
| **NFS-e Inbound worker** | Schedules and runs the ADN query, decodes and classifies each document (NFS-e, DPS, events), generates the DANFSe (NFS-e PDF), applies the cutoff date and history release, sends taker (tomador) manifestations to Sefin Nacional, and runs the daily NSU reconciliation. |
| **Message broker** | Carries messages between stages. There are dedicated queues per product and per stage, dead-letter queues, and delayed retry scheduling. |
| **Document database** | Stores each company's settings, the NSU cursors, document and event metadata, reprocessing controls and the notification audit trail. |
| **Object storage** | Stores the original XML files received from the government, the response batches, the generated PDFs, and the request and response records of the queries. |
| **Distributed cache** | Provides distributed locks (one capture per company at a time, one instance per daily routine), per-company concurrency limits, the control of the NF-e and CT-e point-query limit (20 queries that return a document per hour per CNPJ), and operational parameters that can be tuned at runtime. If the cache becomes unavailable, point queries proceed without the control, and a cStat 656 still blocks the company through the record kept in the database. |
| **Companies and Certificates** | NFE.io platform service that keeps the company registry and holds the A1 digital certificates. Fiscal Document Capture fetches the certificate for each query and keeps it only in memory. |
| **Notifications (Webhooks)** | NFE.io platform service that delivers events to the endpoint configured by the customer. |
| **Usage recording** | Records operations for billing. |
| **NFS-e PDF generation** | Generates the DANFSe from the NFS-e XML. |
| **Observability** | Collects traces, metrics and logs through OpenTelemetry. An external heartbeat alerts the team if any worker stops responding. |

### 4.2 Technology stack

| Layer | Technology |
|---|---|
| Language and runtime | .NET (C#), ASP.NET Core |
| Runtime platform | Containers on Kubernetes, continuous delivery through Helm and GitOps |
| Messaging | RabbitMQ with the Rebus framework |
| Database | MongoDB |
| Cache and locks | Redis-compatible cache |
| File storage | S3-compatible object storage |
| SEFAZ integration | Library for the NF-e and CT-e web services (SOAP, XML signature, mutual TLS) |
| National NFS-e integration | HTTP client with mutual TLS and resilience policies (exponential retry and circuit breaker) |
| Queries | REST with pagination, and OData for NF-e and CT-e |
| Observability | OpenTelemetry and external heartbeat monitoring |

## 5. Deployment

```mermaid
flowchart LR
    subgraph K8S["Kubernetes cluster — Fiscal Document Capture namespace"]
        direction TB
        APIP["API — multiple replicas<br/>CPU-based autoscaling"]
        NFEP["NF-e worker"]
        CTEP["CT-e worker"]
        NFSEP["NFS-e worker"]
    end
    GW["HTTPS gateway"] --> APIP
    SEC["Secrets vault"] -. "credentials injected<br/>at runtime" .-> K8S
```

- The four components (API and three workers) are deployed as independent applications, each with its own container image and release cycle.
- The API runs multiple replicas with horizontal autoscaling. The workers scale parallelism internally, per queue.
- All applications expose readiness checks, which verify the database, cache, broker, storage and dependent services, and liveness checks. Kubernetes takes an instance that is not ready out of load balancing and automatically restarts an instance that stops responding.
- Shutdown is graceful: an instance stops taking new messages and finishes the ones in progress before exiting.
- Credentials (connection strings, keys and service certificates) are kept in a secrets vault and injected at runtime. No credential is stored in source code.
- Scheduled routines (daily NSU reconciliation) run inside the workers, with leader election through a distributed lock. Only one instance runs each cycle.

## 6. Customer integration

### 6.1 REST API

- **Production address:** `https://api.nfse.io`
- **Authentication:** the NFE.io account API key, with authorization by product profile (NF-e, CT-e and NFS-e) or by the general Nota Fiscal key.
- **Data model:** account → company (CNPJ) → capture configuration per product. Document routes are scoped by company: `/v2/companies/{companyId}/inbound/...`.

| Product | Main resources |
|---|---|
| NF-e | Enable, read and disable capture (`.../inbound/productinvoices`); list and view NF-e (`.../inbound/nfe`); download XML and PDF (DANFE); query events; register manifestations; OData queries (`.../inbound/odata/ProductInvoices` and `ProductInvoiceEvents`); resend webhooks. |
| CT-e | Enable, read and disable capture (`.../inbound/transportationinvoices`); download XML, JSON and PDF (DACTE); configure the webhook interested-party filter; reprocess items, batches and webhooks; OData queries (`.../inbound/odata/TransportationInvoices` and `TransportationInvoiceEvents`). |
| NFS-e | Enable capture (`POST /v2/companies/inbound/nfse`) and read, change or disable the configuration (`.../inbound/nfse/details`); list and view documents (`.../inbound/nfse`); download XML, PDF (DANFSe) and JSON; on-demand capture by access key; register taker manifestations; reprocess and resend webhooks. |

XML and PDF downloads are served through a temporary signed URL (usually by HTTP redirect) or directly in the response body, as with the CT-e PDF. Signed URLs expire within an hour and must not be stored; request a new one from the endpoint when needed.

### 6.2 Webhooks

Each captured document or event produces a notification to the endpoint registered by the customer on the NFE.io notification platform.

| Product | Event type | Actions |
|---|---|---|
| NF-e | `product_invoice_inbound` (full document and events) and `product_invoice_inbound_summary` (summaries) | `issued_successfully` (document received), `outbound_successfully` (document issued by the company itself), `event_raised_successfully` (event), `input_event_raised_successfully` (recipient manifestation) |
| CT-e | `transportation_invoice_inbound` | `issued_successfully`, `outbound_successfully`, `event_raised_successfully` |
| NFS-e | `service_invoice_inbound` | `issued_successfully` (NFS-e received), `outbound_successfully` (NFS-e issued by the company itself, when that capture is on), `event_raised_successfully` (events and registered manifestations). The body also carries an `eventName` field in the `inbound.serviceInvoice.*` format |

Delivery is **at-least-once**. The customer system must handle repeated notifications idempotently, using the access key, the event identifier or the NSU. Webhook signature validation follows the official NFE.io webhook documentation.

### 6.3 Console

The `app.nfe.io` console uses the same API to enable capture, query documents, download files and register manifestations. The data is the same in the console and in the API.

## 7. Security and privacy

| Topic | How it is handled |
|---|---|
| **Digital certificate** | Capture uses the company's own **A1 certificate (ICP-Brasil)**, held by the NFE.io certificate service. The certificate is fetched for each query and loaded only in memory. Certificates whose private key is held in an HSM are **not yet supported** by Fiscal Document Capture, which uses the A1 certificate (file) for the mutual TLS required by the distribution environments. |
| **Channel to the government** | All calls to the national environments use HTTPS with mutual authentication (TLS 1.2 or higher). For NFS-e, each request opens its own connection, which isolates one company's certificate from the others. |
| **Channel to the customer** | HTTPS at the gateway, API key authentication and authorization by product profile. |
| **Tenant isolation** | Logical isolation: every record and every query carries the account and company identifier. One account cannot see another account's documents. |
| **Downloads** | Signed URLs with a short validity period. |
| **Internal credentials** | Kept in a secrets vault, with authenticated communication between platform services. |
| **Audit** | Every notification sent is recorded (acceptance time and reach), with 365-day retention. For CT-e, the request and response of every government query are archived; for NF-e, the queries that return documents or rejections. |
| **LGPD (Brazilian data protection law)** | Captured documents contain third-party data (issuers, carriers, service providers). NFE.io acts as the processor of this data on behalf of the customer, who is the legitimate recipient of the documents under the government distribution rules. |

## 8. Resilience

| Mechanism | Description |
|---|---|
| Queues with retries | Every stage that fails is redelivered automatically. Messages that exhaust their attempts go to error queues and can be redriven by the operations team. |
| Message deduplication | Each message has a stable identifier, and the consumer discards duplicates within a time window. |
| Cursor saved after persistence | For CT-e, the NSU cursor only advances after the batch has been persisted. For NF-e and NFS-e, persistence failures are recorded for reprocessing and covered by the daily reconciliation. |
| Pauses during government outages | When the national environment reports a service shutdown, capture is paused for a defined period and resumes on its own (details in document 3). |
| Point-query limit | For NF-e and CT-e, queries by NSU or by access key honor the limit of 20 queries that return a document per hour per CNPJ. Queries with no slot available are deferred without consuming an attempt, with random spacing so that the retries are not concentrated. |
| Circuit breaker | NFS-e has global and per-certificate circuit breakers. For NF-e, a query that fails repeatedly is stopped after the attempt limit so that it does not consume the government service indefinitely. |
| Daily NSU reconciliation | Every day at 11 p.m. (Brasília time), each product checks the NSU sequence of the last 3 days and recovers any missing NSU. |
| External heartbeat | An external monitor receives periodic signals from each worker and alerts the team if any of them stops sending them. |

## 9. Government references

- National NF-e Portal — Technical Note 2014.002 (DF-e Distribution Web Service for NF-e Stakeholders) and the `distDFeInt` and `retDistDFeInt` schemas: https://www.nfe.fazenda.gov.br/portal
- National NF-e Portal — Technical Note 2020.001 (Recipient Manifestation) and Technical Note 2025.002 (Consumption Tax Reform events).
- National CT-e Portal — Technical Note 2015.002 (DF-e Distribution Web Service for CT-e Stakeholders): https://www.cte.fazenda.gov.br/portal
- National NFS-e System — Taxpayer Manual: Guide to the ADN APIs: https://www.gov.br/nfse/pt-br/biblioteca/documentacao-tecnica/documentacao-atual
- CONFAZ — Ajuste SINIEF 07/05 (NF-e): https://www.confaz.fazenda.gov.br/legislacao/ajustes/2005/AJ007_05
