MEI Diagnosis
The accounting service runs a two-phase pipeline to evaluate the fiscal health of a Brazilian MEI (Microempreendedor Individual) across 6 dimensions. This guide walks through the architecture, the data flow, and the API contract.
Big picture
The diagnosis is a fire-and-forget pipeline for data collection, plus a synchronous analysis pass that reads the stored data and returns a structured report.
Phase 1 (update) writes to the DB. Phase 2 (get) reads from the DB. Both run in the same HTTP request — but Phase 1 only blocks on CNPJ; the other 5 areas submit requests and return immediately, with data filled later when providers respond.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /fiscal-entities/:id/mei/diagnosis | Get the latest diagnosis for a fiscal entity (runs Phase 1 + Phase 2) |
| POST | /fiscal-entities/:id/mei/diagnosis | Force-refresh the diagnosis (triggers Phase 1 even when cache is fresh) |
| GET | /fiscal-entities/mei/diagnoses | Accountant view — list all diagnoses for the businesses under the partner |
| GET | /fiscal-entities/:id/mei/diagnoses | List all diagnoses for a fiscal entity (history) |
| POST | /accounting/diagnosis/:cnpj | Update diagnosis by CNPJ (used by upstream flows that don't have the fiscal entity id yet) |
Two-phase pipeline
Every GET or POST on /mei/diagnosis runs the same two phases back-to-back:
SellerFiscalEntity and the linked FiscalEntityMEI.MeiDiagnosis JSON:API document.Phase 1 — Update (fire-and-forget)
The update phase runs the 6 area updates in order. Each one is guarded by a cache check that prevents unnecessary provider calls.
| Area | Sync? | Provider | Skip rule |
|---|---|---|---|
cnpj | SYNC | Serpro (official government API) | Skip if cached recently |
das | ASYNC | Government data providers | Skip months already paid or in divida ativa |
dasn | ASYNC | Government data providers | Skip years already filed |
active_debt | ASYNC | Government data providers | Skip if data exists and is recent |
invoice_emission | N/A | — | Currently always no-op (reserved for future use) |
revenue | ASYNC (per year) | Invoice portal (HTTPS) | Skip if data is fresh. Requires credentials (pass-invoices or digital certificate). |
Phase 2 — Get (synchronous)
The get phase runs the 6 check services sequentially and builds the final report.
Diagnosis ID format
The diagnosis id is deterministic: <fiscalEntityId>.<meiId>.10.<minute * second>. Same fiscal entity at the same minute-of-day always returns the same id — useful for caching.
The 6 areas in detail
CNPJ
Reads the "situacao cadastral" code from Receita Federal. Maps to status: Ativa → succeeded, Suspensa/Inapta/Baixada/Nula → failed, not found → errored.
DAS (monthly tax)
Iterates the last 4 years (48 months) of DAS entries. Each month has a status. The overall DAS status follows priority: errored > processing > failed > succeeded. not-mei and paid months are treated as OK; missing counts as pending; entries stuck in requested for too long become errored.
DASN (annual declaration)
Iterates up to 4 years back, excluding the current year if before June. Each year entry has a status: filed vs unfiled.
Active debt
Checks for active tax debts (inscritos em divida ativa) registered against the MEI. Any active debt → failed. Looks at 5 years back, excluding current year.
Invoice emission
Currently always not_applicable. Reserved for future use.
Revenue
Sums all invoices emitted in the current year and compares with the MEI annual limit (R$ 81k). Bands: < 80% → succeeded, 80–99% → failed with is_warning: true (approaching the cap), ≥ 100% → failed with is_warning: false (exceeded). Requires either a digital certificate or pass_invoices credentials on the fiscal entity — without either, not_applicable. For the full details, see the dedicated Fiscal Entity Revenue guide.
Data sources
The diagnosis fetches data from multiple government sources:
- Serpro — official government API for MEI services (CNPJ lookup, DAS generation, credential validation)
- InfoSimples — third-party data provider that aggregates Receita Federal MEI portal data (DAS list, DASN, active debt)
- Invoice portal — the municipal NFse portal, reached via a thin proxy (requires stored credentials or digital certificate)
JSON:API response shape
{
"data": {
"id": "123.456.10.420",
"type": "fiscal-entity-diagnoses",
"attributes": {
"items": {
"cnpj": { "status": "succeeded", "code": "Ativa" },
"das": { "status": "failed", "pending": ["202409", "202408"], "processing": [], "errored": [] },
"dasn": { "status": "succeeded", "missing": [] },
"active_debt": { "status": "succeeded" },
"invoice_emission":{ "status": "not_applicable" },
"revenue": { "status": "succeeded", "amount": 43210.50, "limit": 81000 }
}
},
"relationships": {
"seller-fiscal-entity": { "data": { "type": "fiscal-entities", "id": "123" } }
}
}
}
Per-area statuses follow the priority order. Empty arrays (no pending, no processing, no errored) are omitted in some serializations.
Retries & caching
The pipeline is designed to be friendly to the government APIs (avoid hammering them) and to be resilient to provider failures.
| Area | Cache / reconsult interval | Retry on error |
|---|---|---|
| CNPJ | Re-fetched after a cooldown period | After cooldown |
| DAS (per month) | Paid months are never re-fetched | Hours |
| DASN (per year) | Filed years are never re-fetched | Weeks |
| Active debt | 5-year window, excludes current year | Weeks |
| Revenue (per year) | Hours | — |
Resilience: when a provider call fails, the system never overwrites good data — it keeps the previous successful value and marks the area as errored. The next request will retry according to the schedule above.