---
title: "Processing flows — NF-e, CT-e and NFS-e Inbound"
description: "Processing flow diagrams of Fiscal Document Capture: scheduling, national environment queries, per-NSU processing, manifestation and gap recovery for NF-e, CT-e and NFS-e."
source_url: https://nfe.io/docs/distribuicao-fluxos-de-processamento-en/
last_updated: 2026-09-25
---

# Fiscal Document Capture Processing Flows — NF-e, CT-e and NFS-e Inbound

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

## 1. How to read this document

This document contains the processing flow diagrams for each sub-product. Each flow has four parts:

1. **Scheduling:** how and when NFE.io decides to query the national environment for a company.
2. **Capture:** the government query and how each possible response is handled.
3. **Per-document processing:** what happens to each NSU received.
4. **Complementary flows:** manifestation, gap recovery and on-demand capture.

The timing rules shown in the diagrams (intervals, waits and blocks) are explained and justified in document 3, with references to the government Technical Notes.

### 1.1 Flow common to all three products

```mermaid
flowchart LR
    A["A third party issues a document<br/>against the customer's CNPJ"] --> B["The government authorizes it and<br/>publishes it in the national<br/>environment with an NSU"]
    B --> C["NFE.io scheduler<br/>selects the company"]
    C --> D["Distribution query<br/>from the last NSU"]
    D --> E["Batch of documents"]
    E --> F["Per-NSU processing:<br/>decompress, classify,<br/>store XML and metadata"]
    F --> G["Webhook to the customer"]
    F --> H["Available in the API<br/>and the console"]
    D -. "no new documents" .-> I["Mandatory<br/>1-hour wait"]
    I -.-> C
```

---

## 2. NF-e Inbound

### 2.1 Scheduling and capture

```mermaid
flowchart TD
    S["Scheduler — every 3 minutes"] --> L["Lists companies with<br/>NF-e capture enabled"]
    L --> E{"Company eligible?<br/>• continuation pending, or<br/>• last query more than 61 min ago"}
    E -- no --> FIM1["Waits for the next cycle"]
    E -- yes --> M["Sends a capture message<br/>with the cursor NSU"]
    M --> P{"SEFAZ paused or<br/>company blocked by a rejection?"}
    P -- yes --> FIM2["No query.<br/>Waits for the pause to end"]
    P -- no --> R{"Cursor already at maxNSU<br/>and last query<br/>less than 62 min ago?"}
    R -- yes --> FIM3["No query.<br/>Observes the 1-hour wait"]
    R -- no --> C["Fetches the company's A1 certificate"]
    C --> Q["distNSU with ultNSU = cursor<br/>NFeDistribuicaoDFe — National Environment"]
    Q --> ARQ["Reads the response"]
    ARQ --> K{"cStat"}
    K -- "138 — documents found" --> B1["Archives the response, stores the batch<br/>and creates one item per NSU"]
    B1 --> B2["Sends one processing<br/>message per NSU"]
    B2 --> B3["Updates the cursor:<br/>ultNSU and maxNSU"]
    B3 --> B4{"ultNSU lower than maxNSU?"}
    B4 -- yes --> M
    B4 -- no --> FIM4["Queue drained.<br/>Next query after 1 hour"]
    K -- "137 — no documents" --> N1["Records the query time"] --> FIM4
    K -- "108 or 109 — service shut down" --> G1["Global query pause:<br/>5 min — 108<br/>20 min — 109"]
    K -- "656 — improper consumption" --> G4["Blocks the company for 1 hour,<br/>suspends the CNPJ's point queries<br/>and moves the cursor to ultNSU, forward only"]
    K -- "other rejection" --> G2["Blocks the company for 1 hour<br/>and records the error"]
    K -- "communication failure" --> G3["Automatic retry.<br/>After the attempt limit,<br/>the query is stopped<br/>for operations review"]
```

### 2.2 Processing each NSU

```mermaid
flowchart TD
    A["NSU processing message"] --> B["Reads the archived batch and finds<br/>the docZip for the NSU"]
    B --> C["Base64-decodes and GZip-decompresses"]
    C --> D{"Document schema"}
    D -- "resNFe" --> R1["NF-e summary"]
    D -- "procNFe" --> R2["Full authorized NF-e"]
    D -- "resEvento" --> R3["Event summary"]
    D -- "procEventoNFe" --> R4["Full event"]
    R1 & R2 & R3 & R4 --> E["Extracts metadata:<br/>key, issuer, recipient,<br/>carrier, amounts, dates"]
    E --> F["Determines direction:<br/>received or issued by the company"]
    F --> G["Stores the XML in object storage<br/>and the metadata in the database"]
    G --> H["Links events to the NF-e with the same key"]
    H --> I["Sends the webhook"]
    I --> J["Records usage"]
    J --> K{"resNFe summary with<br/>automatic Awareness enabled?"}
    K -- yes --> MAN["Manifestation flow — section 2.3"]
    K -- no --> FIM["Done"]
```

### 2.3 Recipient manifestation and release of the full XML

```mermaid
sequenceDiagram
    autonumber
    participant AN as NF-e National Environment
    participant W as NF-e worker
    participant EV as NFeRecepcaoEvento4
    participant API as NFE.io API
    participant CLI as Customer system

    W->>AN: distNSU
    AN-->>W: resNFe — NF-e summary, NSU n
    W->>CLI: webhook product_invoice_inbound_summary
    alt Automatic Awareness enabled
        W->>W: Schedules event 210210 — Awareness of Operation, no duplicates per key
        Note over W: Waits for the waiting time set by the company
        W->>W: Checks again: automatic Awareness still on and no accepted conclusive manifestation
        W->>EV: envEvento signed with the A1 certificate
        EV-->>W: cStat 135 or 136 — event registered
    else Manifestation by the customer
        CLI->>API: POST manifestation — 210200, 210210, 210220 or 210240
        API-->>CLI: 202 — pending
        API->>W: submission message
        W->>EV: signed envEvento
        EV-->>W: registration result
    end
    Note over AN,W: After Awareness, Confirmation or Operation Not Performed, the National Environment releases the full XML to the recipient
    Note over W,CLI: Awareness is the only automatic manifestation. Confirmation, Unknown Operation and Operation Not Performed are always sent at the customer's request
    W->>AN: distNSU — normal cycle
    AN-->>W: procNFe — full NF-e, new NSU m
    W->>CLI: webhook product_invoice_inbound — issued_successfully
    AN-->>W: procEventoNFe — manifestation event
    W->>CLI: webhook input_event_raised_successfully
```

### 2.4 NSU gap recovery

```mermaid
flowchart LR
    A["Daily routine — 11 p.m. Brasília time<br/>a single instance, via distributed lock"] --> B["For each active company:<br/>NSUs captured in the last 3 days"]
    B --> C["Checks the sequence in the<br/>minimum–maximum range"]
    C --> D["Missing NSU becomes<br/>a recovery item"]
    D --> E["Dispatcher — every 5 min"]
    E --> F["consNSU for the missing NSU<br/>within the point-query limit — section 2.5"]
    F -- success --> G["Processes as in section 2.2<br/>and closes the item"]
    F -- failure --> H["Retry with exponential wait<br/>1 min to 30 min, with random jitter,<br/>up to 8 attempts"]
    H -- exhausted --> I["Item is evaluated again<br/>in the next daily routine"]
```

### 2.5 Point queries and consumption limit (NF-e and CT-e)

Applies to `consNSU` and `consChNFe` for NF-e and to `consNSU` for CT-e, both in gap recovery and in reprocessing requested by the customer.

```mermaid
flowchart TD
    A["Point-query request<br/>gap recovery or reprocessing"] --> L{"NF-e: document already<br/>in the NFE.io database?"}
    L -- yes --> LOC["Resends from the database.<br/>Does not query SEFAZ or use the quota"]
    L -- "no, or CT-e" --> V{"Slot available in the CNPJ limit?<br/>20 queries that return a document per hour"}
    V -- "no, or CNPJ blocked by 656" --> AD{"Request origin"}
    AD -- "internal queue" --> DEF["Deferred until the next slot,<br/>with random spacing of up to 30 min.<br/>Does not count as an attempt"]
    AD -- "API" --> R429["Responds HTTP 429<br/>with Retry-After"]
    V -- yes --> C["Gets the certificate and<br/>queries SEFAZ"]
    C --> K{"Response"}
    K -- "document returned" --> OK["Processes the document.<br/>The query counts toward the quota"]
    K -- "656 — improper consumption" --> B["Blocks the CNPJ's point queries<br/>for 1 hour. For NF-e, distribution too.<br/>The slot is returned"]
    K -- "no document, other rejection<br/>or failure" --> DV["Returns the slot:<br/>only queries that return a document count"]
```

---

## 3. CT-e Inbound

### 3.1 Scheduling and capture

```mermaid
flowchart TD
    S["Scheduler — every 60 seconds"] --> L["Lists companies with<br/>CT-e capture enabled"]
    L --> E{"Company eligible?<br/>• continuation pending, or<br/>• last query more than 60 min ago"}
    E -- no --> FIM1["Waits for the next cycle"]
    E -- yes --> M["Sends a capture message<br/>with the cursor NSU"]
    M --> P{"SEFAZ paused or<br/>company blocked by a rejection?"}
    P -- yes --> FIM2["No query.<br/>Waits for the pause to end"]
    P -- no --> R{"Last response indicated the end<br/>of the queue less than 1 hour ago?"}
    R -- yes --> FIM3["No query.<br/>Observes the 1-hour wait"]
    R -- no --> C["Fetches the company's A1 certificate"]
    C --> Q["distNSU with ultNSU = cursor<br/>CTeDistribuicaoDFe — National Environment"]
    Q --> ARQ["Archives request and response"]
    ARQ --> K{"cStat"}
    K -- "138 — documents found" --> B1["Stores the batch and one item per NSU,<br/>with controlled parallelism"]
    B1 --> B2{"Batch persisted?"}
    B2 -- yes --> B3["Advances the cursor:<br/>ultNSU and maxNSU"]
    B2 -- "no" --> B5["Cursor does not advance.<br/>Failed NSUs become<br/>recovery items"]
    B3 --> B4{"ultNSU lower than maxNSU?"}
    B4 -- yes --> M
    B4 -- no --> FIM4["Queue drained.<br/>Resumes at the next eligible cycle"]
    K -- "137 — no documents" --> N1["Advances the cursor and records<br/>the time"] --> FIM5["Next query after 1 hour"]
    K -- "108 or 109 — service shut down" --> G1["Global query pause:<br/>5 min — 108<br/>20 min — 109"]
    K -- "other rejection, including 656" --> G2["Blocks the company for 1 hour<br/>and records the error"]
```

### 3.2 Processing each NSU

```mermaid
flowchart TD
    A["NSU processing message"] --> B["Reads the archived batch and finds<br/>the docZip for the NSU"]
    B --> C["Base64-decodes and GZip-decompresses"]
    C --> D{"Document schema"}
    D -- "procCTe" --> R1["Full authorized CT-e"]
    D -- "procEventoCTe" --> R2["CT-e event"]
    R1 --> E1["Extracts metadata: key, issuer,<br/>sender, dispatcher, receiver,<br/>recipient, taker, service amount,<br/>referenced NF-e"]
    R2 --> E2["Extracts event metadata:<br/>type, sequence, registration date"]
    E2 --> F2{"Is the event type in the list<br/>configured by the company?"}
    F2 -- no --> IG["Stored as an ignored event.<br/>No webhook"]
    F2 -- yes --> G
    E1 --> DIR["Determines direction:<br/>issued only if the company is<br/>solely the issuer"]
    DIR --> G["Stores the XML and the metadata"]
    G --> PI{"Interested-party filter<br/>configured?"}
    PI -- "no" --> WH["Sends the webhook"]
    PI -- "yes and the company holds the role" --> WH
    PI -- "yes and the company does not hold the role" --> SUP["Document stays available in the API,<br/>no webhook"]
    WH --> U["Records usage"]
```

### 3.3 Gap recovery and reprocessing

```mermaid
flowchart LR
    A["Daily routine — 11 p.m.<br/>Brasília time"] --> B["NSUs from the last 3 days<br/>and a scan up to the current cursor"]
    B --> C["Missing NSU becomes a recovery item"]
    C --> D["Dispatcher — every 5 min"]
    D --> E["consNSU for the missing NSU<br/>within the point-query limit — section 2.5"]
    E -- "success" --> F["Processes as in section 3.2"]
    E -- "137 — NSU does not exist" --> T["Closes the item"]
    E -- "other responses" --> H["Retry with exponential wait<br/>1 min to 30 min, with random jitter,<br/>up to 8 attempts"]
    R["Reprocessing request<br/>through the API — item, batch or webhook"] --> D
```

The CT-e distribution web service has no query by access key. All recovery is done by NSU.

---

## 4. NFS-e Inbound

### 4.1 Scheduling and capture

```mermaid
flowchart TD
    S["Scheduler — every 30 seconds"] --> L["Selects active companies<br/>outside a wait period"]
    L --> M["Sends one capture message per company"]
    M --> LK{"Company lock free?<br/>one capture per company at a time"}
    LK -- no --> FIM1["Discarded: a capture is already running"]
    LK -- yes --> CERT{"Valid A1 certificate?"}
    CERT -- "missing, expired or in an HSM" --> CD1["1-hour wait.<br/>Company stays active and<br/>resumes on its own"]
    CERT -- yes --> Q["GET /DFe/NSU — ADN<br/>distribution batch from the cursor"]
    Q --> K{"ADN response"}
    K -- "DOCUMENTOS_LOCALIZADOS" --> B1["Sends one processing<br/>message per document"]
    B1 --> B2["Saves the cursor — highest NSU received"]
    B2 --> B3{"Limit of 50 batches<br/>in this run reached?"}
    B3 -- no --> Q
    B3 -- yes --> FIM2["Continues in the next cycle"]
    K -- "NENHUM_DOCUMENTO_LOCALIZADO" --> CD2["Saves the cursor.<br/>1-hour wait"]
    K -- "HTTP 429 — consumption limit" --> CD3["Waits for the time indicated by the ADN<br/>or 1 hour"]
    K -- "REJEICAO" --> RJ["Records the error codes.<br/>Nothing captured in this run: 10-min wait.<br/>Documents already captured: retried in the next cycle"]
    K -- "certificate rejected" --> CB["Counts a consecutive failure.<br/>After 10 failures, the company's<br/>capture is disabled"]
    K -- "transient 5xx failure or timeout" --> PO["Up to 3 retries — 1 s, 2 s, 4 s.<br/>Per-certificate and global circuit breakers.<br/>If it persists, rescheduled with an<br/>exponential wait from 1 min to 1 h"]
```

### 4.2 Processing each document

```mermaid
flowchart TD
    A["Processing message"] --> ID{"NSU already processed<br/>for the company?"}
    ID -- yes --> FIM1["Ignored — idempotency"]
    ID -- no --> B["Decodes Base64, GZip and UTF-8"]
    B --> C{"XML root element"}
    C -- "NFSe" --> T1["Authorized NFS-e"]
    C -- "DPS" --> T2["Service Provision Declaration"]
    C -- "event or event request" --> T3["Event — cancellation, replacement,<br/>manifestations, ex officio acts"]
    C -- "CNC" --> T4["National Taxpayer Register"]
    T1 & T2 & T3 & T4 --> D["Stores the compressed XML<br/>in object storage"]
    D --> P{"Is it an NFS-e?"}
    P -- yes --> PDF["Generates the DANFSe.<br/>If unavailable, it stays pending and is<br/>generated on demand at download"]
    P -- no --> MD
    PDF --> MD["Extracts metadata: provider, taker,<br/>intermediary, service, amounts and taxes,<br/>including IBS and CBS"]
    MD --> DIR["Determines direction:<br/>received or issued"]
    DIR --> CUT{"Document earlier than the<br/>company's cutoff date?"}
    CUT -- "yes, history not released" --> SK["Stored without webhook.<br/>Delivered only if history is released"]
    CUT -- no --> OUT{"NFS-e issued by the company itself?"}
    OUT -- "yes and issued-document capture is off" --> SK2["Stored without webhook"]
    OUT -- "no, or issued-document capture is on" --> WH["Sends the webhook"]
    WH --> U["Records usage"]
```

### 4.3 Taker manifestation and on-demand capture

```mermaid
sequenceDiagram
    autonumber
    participant CLI as Customer system
    participant API as NFE.io API
    participant W as NFS-e worker
    participant SEFIN as Sefin Nacional / ADN

    rect rgba(127,127,127,0.08)
    Note over CLI,SEFIN: Taker manifestation — always at the customer's request, never automatic
    CLI->>API: POST manifestation — 203202 Confirmation or 203206 Rejection
    API-->>CLI: 202 — pending
    API->>W: submission message
    W->>W: Checks the certificate and the taker CNPJ
    W->>SEFIN: POST signed event registration request
    SEFIN-->>W: event registered or rejected
    alt event registered
        W->>CLI: webhook event_raised_successfully
    else event rejected
        W->>W: records the rejection, available in the API
    end
    end

    rect rgba(127,127,127,0.08)
    Note over CLI,SEFIN: On-demand capture by access key
    CLI->>API: POST capture by key — 50 digits
    API->>SEFIN: GET NFS-e by key
    SEFIN-->>API: NFS-e XML
    API->>API: Stores it, generates the PDF and saves metadata
    API-->>CLI: 200 — document captured, no webhook at this point
    Note over CLI,SEFIN: The webhook is sent when the document arrives through normal distribution
    end
```

### 4.4 Gap recovery

```mermaid
flowchart LR
    A["Daily routine — 11 p.m.<br/>Brasília time"] --> B["NSUs captured in the last 3 days"]
    B --> C["Checks the sequence in the range"]
    C --> D{"Any gap?"}
    D -- yes --> E["Restarts the company's capture<br/>from the NSU before the first gap"]
    E --> F["Documents that already exist are ignored<br/>through idempotency; missing ones are stored"]
    D -- no --> G["Nothing to do"]
```

---

## 5. Query cadence life cycle (all three products)

```mermaid
stateDiagram-v2
    [*] --> Active: capture enabled
    Active --> Querying: scheduler selects the company
    Querying --> Querying: documents pending in the national environment
    Querying --> Waiting: end of queue — no new documents
    Waiting --> Querying: after 1 hour
    Querying --> Blocked: national environment rejection
    Blocked --> Querying: block ends
    Querying --> GlobalPause: national environment shut down or failing
    GlobalPause --> Querying: pause ends
    Active --> [*]: capture disabled
```

| State | NF-e | CT-e | NFS-e |
|---|---|---|---|
| **Querying** | Chained queries while `ultNSU` is lower than `maxNSU` | Chained queries while `ultNSU` is lower than `maxNSU` | Up to 50 consecutive batches per run, resuming every 30 s |
| **Waiting** | At least 1 hour after reaching `maxNSU` or receiving cStat 137 (up to about 65 min) | At least 1 hour after the environment signals the end of the queue (cStat 137) | 1 hour after `NENHUM_DOCUMENTO_LOCALIZADO` |
| **Blocked** | 1 hour per company after a rejection, including 656; 656 also suspends the CNPJ's point queries | 1 hour per company after a rejection, including 656; a 656 on a point query suspends the CNPJ's point queries | Time given by the ADN in the HTTP 429, or 1 hour; 10 min after a `REJEICAO` with no documents captured; 1 hour for an unavailable certificate |
| **Global pause** | 5 min (cStat 108) and 20 min (cStat 109) | 5 min (cStat 108) and 20 min (cStat 109) | Global and per-certificate circuit breaker, 60 s |
