Swagger UI openapi.json openapi.yaml
Guide

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.

Your app
accounting
InfoSimples / Serpro
Receita Federal

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

MethodPathPurpose
GET/fiscal-entities/:id/mei/diagnosisGet the latest diagnosis for a fiscal entity (runs Phase 1 + Phase 2)
POST/fiscal-entities/:id/mei/diagnosisForce-refresh the diagnosis (triggers Phase 1 even when cache is fresh)
GET/fiscal-entities/mei/diagnosesAccountant view — list all diagnoses for the businesses under the partner
GET/fiscal-entities/:id/mei/diagnosesList all diagnoses for a fiscal entity (history)
POST/accounting/diagnosis/:cnpjUpdate 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:

accounting
Resolves the SellerFiscalEntity and the linked FiscalEntityMEI.
accounting
Phase 1 — Update — kicks off the 6 area updates.
accounting → Serpro/InfoSimples
Each area fetches the data it needs (sync for CNPJ, async for the rest).
accounting
Phase 2 — Get — reads the just-written data and computes statuses.
accounting
Returns the 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.

AreaSync?ProviderSkip rule
cnpjSYNCSerpro (official government API)Skip if cached recently
dasASYNCGovernment data providersSkip months already paid or in divida ativa
dasnASYNCGovernment data providersSkip years already filed
active_debtASYNCGovernment data providersSkip if data exists and is recent
invoice_emissionN/ACurrently always no-op (reserved for future use)
revenueASYNC (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.

AreaCache / reconsult intervalRetry on error
CNPJRe-fetched after a cooldown periodAfter cooldown
DAS (per month)Paid months are never re-fetchedHours
DASN (per year)Filed years are never re-fetchedWeeks
Active debt5-year window, excludes current yearWeeks
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.