Architecture of NF-e and NFC-e Issuance and Tax Calculation
| Product | NFE.io Product Invoice Issuance (dfetech-product-invoice-api): NF-e, NFC-e, Tax Calculation (Taxes) and Tax Payment Slips (Taxes Payment Forms) |
| Document | 1 of 4: Architecture design |
| Version | 1.0 (2026-09-24) |
| Audience | Customers, architecture teams, IT, information security and tax departments |
| Related documents | 2 of 4: Processing flows · 3 of 4: Processing, resilience, idempotency and contingency · 4 of 4: Messaging and queues (Portuguese) · Versão em português |
1. Summary
The NFE.io product invoice platform receives the data of a sale or goods movement through a REST API. It calculates taxes when the customer asks for it, generates the XML and signs it with the company's digital certificate, obtains SEFAZ authorization, stores the files and notifies the customer's system by webhook.
The solution has four subproducts that share the same platform:
| Subproduct | What it does | Tax document | Government counterpart |
|---|---|---|---|
| NF-e | Issues, cancels, corrects (CC-e) and disables numbers of the Nota Fiscal Eletrônica. Also issues return, complementary, credit and debit invoices. | NF-e, model 55 | Authorizing SEFAZ of the issuer's state (own or virtual) and National Environment (Ambiente Nacional, EPEC) |
| NFC-e | Issues, cancels and disables numbers of the Nota Fiscal de Consumidor Eletrônica, with asynchronous or synchronous issuance and offline contingency. | NFC-e, model 65 | Authorizing SEFAZ of the issuer's state (own or virtual) |
| Taxes (Tax Calculation) | Calculates ICMS, ICMS-ST, FCP, DIFAL, IPI, PIS, COFINS, IBS and CBS per item and maintains the product tax registry. Serves NF-e, NFC-e and direct customer calls. | Issues no document | Does not communicate with SEFAZ |
| Taxes Payment Forms (Tax Payment Slips) | Generates the interstate DIFAL payment slip (GNRE or DUA) from an authorized NF-e. | GNRE / DUA | GNRE portal and SEFAZ-ES |
NF-e and NFC-e share the same business domain, the same XML generation engine and the same SEFAZ communication layer. They run as separate applications, with their own queues, data stores and scaling. An outage or a volume spike in one product does not affect the other.
2. Architecture principles
- Asynchronous, message-driven issuance. The API validates the request, records it and immediately responds with the invoice identifier. Issuance continues in the background, in steps decoupled by queues (numbering, signing, sending, status query, notification). Each step can be retried without redoing the previous ones. NFC-e also offers a synchronous mode with a maximum response time.
- Event Sourcing. Each invoice is an aggregate whose state is the sum of its events (created, numbered, signed, authorized, cancelled, etc.). Nothing is overwritten: the full history is available for auditing and the flow always resumes from the last recorded event.
- One execution per invoice. A distributed lock per invoice ensures that only one process works on each invoice at a time. An admission control prevents the same operation on an invoice from producing two concurrent executions (this does not apply to resending the issuance
POST, which creates a new invoice). - Never resend blindly. When communication with SEFAZ ends without a conclusive response (timeout), the platform queries the invoice status by access key before any resend. This avoids duplicate rejections and double issuance.
- Separation by product. NF-e, NFC-e, Taxes and Payment Forms are independent applications, each with its own container image, release cycle, queues and scaling.
- Tax calculation as a service. Tax calculation is a separate service. NF-e and NFC-e call it when the invoice is created, and customers can also call it before issuing.
- Fail closed on calculation. If taxes cannot be calculated safely, the invoice is not issued with assumed values: it waits for the service to recover or is refused with the reason.
- Legally defined contingency. Contingency modes follow the Manual de Orientação do Contribuinte (MOC, taxpayer guidance manual) and the Ajustes SINIEF: EPEC for NF-e and offline contingency for NFC-e.
- End-to-end observability. All components emit distributed traces, metrics and structured logs and expose health checks.
3. Overview (context diagram)
4. Component view
4.1 Component responsibilities
| Component | Responsibility |
|---|---|
| HTTPS Gateway | Terminates TLS and routes the public NF-e, NFC-e, Taxes and Payment Forms routes to the respective APIs. |
| NF-e API | Receives requests for issuance, cancellation, Carta de Correção Eletrônica (CC-e, correction letter), inutilização (number disablement) and fiscal events. Validates the payload and the registry, records the request and puts it in the queue. Serves the invoice query, the listing, the XML and the PDF (DANFE). Runs number range disablement synchronously. Scales horizontally based on CPU and memory usage. |
| NF-e Worker | Runs each issuance step: invoice creation and tax calculation, numbering, signing, sending to SEFAZ, query by access key, assembly of the distribution XML (nfeProc) and notification. Runs cancellation, CC-e, number disablement and EPEC contingency. |
| NFC-e API | Same responsibilities as the NF-e API, for NFC-e. In synchronous mode, it creates the invoice and calculates taxes within the request itself and calls the worker directly to obtain authorization within the deadline. |
| NFC-e Worker | Runs the NFC-e steps, including synchronous authorization with a maximum deadline, offline contingency and retransmission of invoices issued in contingency. |
| Read Model Worker | Keeps the query index (listings and searches) up to date from invoice events. A query for a specific invoice always reads the event store, which is the source of truth. |
| Taxes API | Calculates taxes per item, maintains the product tax registry and publishes code tables (nature of operation, acquisition purpose, tax profiles). Validates and activates registered products in the background. |
| Taxes Payment Forms API | Generates interstate DIFAL payment slips (GNRE or DUA) from an authorized NF-e, transmits the batch to the government portal and delivers the slip PDF and XML. |
| Message broker | Carries messages between steps. Each product has its own queue, error queue (dead-letter) and delayed retry scheduling. Document 4 details the topology and the queues. |
| Event store and snapshots | Stores each invoice's events, with optimistic concurrency control, and periodic snapshots to speed up reads. |
| Object storage | Stores the original request, the signed XML, the sent batch, the authorized XML (nfeProc), the rejection XML, the EPEC event XML, the CC-e XMLs and PDFs, and the DANFE. |
| Query index | Elasticsearch, used for invoice and payment slip listings and searches. |
| Distributed cache | Per-invoice locks, work admission control, contingency flag per state (NF-e) and contingency circuit breaker per state (NFC-e). Also stores the Taxes feature flags. |
| MongoDB | Retry scheduling, deduplication of received messages, Taxes product and scenario registry, and payment slip records. |
| Companies, State Tax Registrations and numbering | Platform service that maintains the company registry and the inscrições estaduais (state tax registrations, IE) (series, environment, NFC-e CSC, contingency strategy) and controls the numbering sequence per series. |
| A1 Certificate Custody | Platform service that holds the companies' ICP-Brasil digital certificates. The certificate is fetched for each operation and used in memory. |
| Notifications (Webhooks) | Platform service that delivers events to the endpoint configured by the customer, with HMAC signature and automatic redelivery. |
| Usage recording | Counts operations for billing purposes. |
| Tax rules engine | Rules base from a specialized partner, queried by Taxes for ICMS, ICMS-ST, FCP, DIFAL, IPI, PIS and COFINS. IBS and CBS are calculated by an NFE.io in-house service. |
4.2 Technology stack
| Layer | Technology |
|---|---|
| Language and runtime | .NET 10 (C#), ASP.NET Core |
| Execution | Containers on Kubernetes, continuous delivery via Helm and GitOps |
| Messaging | RabbitMQ with the Rebus framework |
| Invoice persistence | Event Sourcing on cloud table storage, with snapshots |
| Files | Cloud object storage |
| Query and listing | Elasticsearch |
| Cache, locks and controls | Redis-compatible cache |
| Scheduling and deduplication | MongoDB |
| SEFAZ integration | Communication library for the NF-e and NFC-e Web Services (SOAP 1.2, XML signature, mutual TLS, XSD schema validation) |
| Layout | NF-e/NFC-e version 4.00, with the Consumption Tax Reform groups (IBS, CBS and IS) from NT 2025.002 |
| DANFE | In-house PDF generation (portrait and landscape DANFE, NFC-e DANFE and CC-e DANFE) |
| Observability | OpenTelemetry (traces, metrics and logs) and external heartbeat monitoring |
5. Deployment
- The seven applications are deployed independently, each with its own container image and release cycle.
- The APIs run with multiple replicas and horizontal autoscaling by CPU (and, for NF-e, also by memory). The workers process several messages in parallel per replica.
- All applications expose a liveness check (
/healthz/live) and a readiness check (/healthz/ready). In the issuance applications, the readiness check verifies the event store, object storage, broker, cache and the registry and certificate services. Kubernetes removes an instance that is not ready from load balancing and restarts an instance that stops responding. - Shutdown is graceful: the instance stops receiving messages and finishes the ones in progress.
- Credentials (connection strings, keys and service certificates) are kept in a secrets vault and injected at runtime. No credential is stored in source code.
- Operational parameters (synchronous NFC-e deadlines, offline contingency, queues, locks) are defined in each environment's deployment configuration and versioned with the code.
6. Customer integration
6.1 REST API
- Production address:
https://api.nfse.io - Authentication: NFE.io account API key, with authorization by product profile.
- Versions:
v2andv3.v3accepts the alphanumeric CNPJ; an invoice with an alphanumeric CNPJ is not shown byv2. - Data model: account → company (CNPJ) → state tax registration (IE) → invoice. Routes are scoped by company.
| Product | Main resources |
|---|---|
| NF-e | Issue (POST /v2/companies/{companyId}/productinvoices or .../statetaxes/{statetaxId}/productinvoices); query, list, and query items and events; cancel (DELETE .../{id}); correction letter (PUT .../{id}/correctionletter); download the authorized XML, rejection XML, EPEC XML and PDF (DANFE); disable the number of a refused invoice (POST .../{id}/disablement) or a range (POST .../productinvoices/disablement); link and list credit invoices. |
| NFC-e | Issue asynchronously (POST /v2/companies/{companyId}/consumerinvoices) or synchronously (POST .../consumerinvoices/sync); query, list, items and events; cancel; download XML and PDF (NFC-e DANFE); disable the number of a refused invoice or a range. |
| Taxes | Calculate taxes (POST /tax-rules/{tenantId}/engine/calculate); register, query and update products (/{tenantId}/products); query code tables (/tax-codes/...). |
| Payment Forms | Generate a payment slip from an NF-e issued by NFE.io (POST /v1/tax-payment-forms/{accountId}/{companyId}/gnre) or from an XML (.../gnre/xml); query the slip and download the PDF. |
| Registry | Companies, certificates and state tax registrations, including the manual switch of authorizer for contingency (POST /v2/companies/{company_id}/statetaxes/{state_tax_id}/switch-authorizer). |
XML and PDF downloads are delivered as a file access URL. The full contracts are in the OpenAPI specifications published in the NFE.io documentation.
6.2 Webhooks
Each relevant state change generates a notification to the endpoint registered by the customer.
| Product | Event type | Actions |
|---|---|---|
| NF-e | product_invoice | issued_successfully, issued_error, issued_failed, cancelled_successfully, cancelled_error, cancelled_failed, cce_successfully, cce_error, cce_failed, disabled_successfully, disabled_error, disabled_failed and, for the Tax Reform fiscal events, dfe_event_successfully, dfe_event_error, dfe_event_failed, dfe_event_cancelled |
| NFC-e | consumer_invoice | issued_successfully, issued_error, issued_failed, issued_contingency, cancelled_*, disabled_* |
| Taxes | product_tax | created_successfully (product active), custom_rules_requested (custom taxation under review), creation_failed (error) |
| Payment Forms | tax_payment_form | created_successfully (slip generated), creation_failed (error), creation_not_needed (slip not required) |
- The
_errorsuffix indicates a one-off failure (SEFAZ rejection or validation error). The_failedsuffix indicates that retries are exhausted. Some limits end with_error, such as the limit on queries returning 217 and the limit on tax calculation attempts (document 3). - The body carries the full invoice resource, with
statusand the recent history inlastEvents. - Delivery is at-least-once, with automatic redelivery and HMAC signature. The customer's system must handle repeated notifications idempotently, using the
X-Hook-Idheader and the invoiceid. The full policy is in the webhook event catalog (Portuguese).
6.3 Console
The app.nfe.io console uses the same APIs to issue, query, download files, cancel and disable numbers. There is no data difference between the console and the API.
7. Security and privacy
| Topic | How it is handled |
|---|---|
| Digital certificate | XML signing and mutual TLS with SEFAZ use the company's own A1 (ICP-Brasil) certificate, held by the NFE.io certificate service. The certificate is fetched for each operation, used in memory and discarded at the end of the call. Validity is checked before signing: an expired or not yet valid certificate ends issuance with an error, without calling SEFAZ. |
| Government channel | HTTPS with mutual authentication, TLS 1.2 or higher. The XML is validated against the official schemas before sending. |
| Customer channel | HTTPS at the gateway, API key authentication and authorization by product profile. In Taxes, the account in the route must match the API key's account; otherwise, the call returns HTTP 403. |
| Customer isolation | Logical isolation: every record and every query carries the account and company identifiers. One account cannot see another account's invoices. |
| Internal credentials | Kept in a secrets vault, with authenticated communication between platform services. |
| NFC-e CSC | The Código de Segurança do Contribuinte (taxpayer security code) and its identifier are stored in the state tax registration record and used only to generate the QR Code. |
| Audit | Each invoice keeps the full event sequence (request, calculation, numbering, signing, sending, SEFAZ response, notification), with date and time, plus the XMLs sent and received. |
| LGPD | Invoices contain recipients' personal data (name, CPF, address). NFE.io acts as processor of this data on behalf of the issuing customer, who is the controller. The data is used only to issue, store and deliver the documents. |
8. Resilience
| Mechanism | Description |
|---|---|
| Steps with retries | Each step that fails for a transient reason is rescheduled with increasing waits. When the retry limit is exhausted, the invoice ends with the _failed action (or _error, for the limits on 217 queries and on tax calculation) and the reason. Document 3 lists the intervals. |
| Error queues | Messages that repeatedly fail delivery go to an error queue and can be reprocessed by the operations team, without losing the request. |
| Query before resending | A timeout or duplicate at SEFAZ leads to a query by access key, never to a blind resend. |
| Per-invoice lock and admission control | A single execution per invoice and per operation; repeated requests for an operation on the same invoice, while it is in progress, are discarded. Resending the issuance POST creates a new invoice. |
| Message deduplication | The consumer discards the redelivery of an already processed message within a 5-minute window. |
| Resumption from the event store | Any step resumes from the invoice's last recorded event. |
| Certificate validation before sending | Avoids useless attempts with an invalid certificate. |
| Contingency | EPEC for NF-e and offline contingency for NFC-e, detailed in document 3. |
| Tax calculation with retry and fallback | Retries on transient tax engine failures and use of a recently stored calculation when the engine is unavailable, under strict rules. |
| Health checks and heartbeat | Unhealthy instances leave load balancing; an external monitor alerts the team if any component stops responding. |
9. Government references
- Portal Nacional da NF-e (National NF-e Portal), Manual de Orientação do Contribuinte (MOC, taxpayer guidance manual) version 7.0 (Visão Geral: overview; Anexo I: Leiaute e Regras de Validação, layout and validation rules; Anexo III: Manual de Contingência da NF-e, NF-e contingency manual; Anexo IV: Manual de Contingência da NFC-e, NFC-e contingency manual): https://www.nfe.fazenda.gov.br/portal/listaConteudo.aspx?tipoConteudo=ndIjl+iEFdE%3D
- Portal Nacional da NF-e (National NF-e Portal), Notas Técnicas (technical notes), including NT 2025.002 (Reforma Tributária do Consumo, Consumption Tax Reform) and NT 2014.001 (EPEC): https://www.nfe.fazenda.gov.br/portal/listaConteudo.aspx?tipoConteudo=04BIflQt1aY%3D
- Portal Nacional da NF-e (National NF-e Portal), Relação de Serviços Web (web services list: authorizers per state and SVC): https://www.nfe.fazenda.gov.br/portal/webServices.aspx?tipoConteudo=OUC/YVNWZfo%3D
- CONFAZ, Ajuste SINIEF 07/05 (NF-e): https://www.confaz.fazenda.gov.br/legislacao/ajustes/2005/AJ007_05
- CONFAZ, Ajuste SINIEF 19/16 (NFC-e): https://www.confaz.fazenda.gov.br/legislacao/ajustes/2016/AJ_019_16