Architecture
How Meefi Analytics fits into your integration: resources, data flow, and how invoice amounts are derived.
System context
flowchart TB
subgraph Client["Your product"]
App[Application / backend]
Hook[Webhook handler]
end
subgraph Meefi["Meefi Analytics"]
API["REST API
/v1"]
Worker[Background processing]
API --> Worker
end
subgraph External["External systems"]
SAT[SAT CFDI portal]
end
App <-->|"HTTP Basic · JSON"| API
API -->|"POST events
Bearer token"| Hook
Worker <-->|"CIEC session"| SAT| Layer | Responsibility |
|---|---|
API (/v1) |
Entities, extractions, invoices, webhooks |
| Background processing | SAT sync, XML parsing, aggregate updates |
All API resources belong to your organization. Requests cannot access another organization's data.
Core resources
erDiagram
ORGANIZATION ||--o{ ENTITY : owns
ORGANIZATION ||--o{ WEBHOOK : owns
ENTITY ||--o{ EXTRACTION : runs
ENTITY ||--o{ INVOICE : contains
INVOICE ||--o{ PAYMENT : "type P only"
INVOICE ||--o{ INVOICE_RELATION : links
ORGANIZATION {
uuid id
string name
}
ENTITY {
uuid id
string tax_id
string credential_status
}
EXTRACTION {
uuid id
string status
json options
}
INVOICE {
uuid id
string uuid
string type
string status
}Entity
One SAT taxpayer (RFC) registered with a CIEC password. The service validates credentials with the SAT before extractions can succeed.
credential_status |
Meaning |
|---|---|
pending |
Validation in progress |
valid |
CIEC accepted |
invalid |
CIEC rejected — update the password |
error |
SAT unreachable after retries |
Extraction
An asynchronous job that downloads CFDI for a date range, parses XML, links related documents, and refreshes financial aggregates.
| Status | Meaning |
|---|---|
pending |
Queued |
running |
Download or processing in progress |
finished |
Completed successfully |
failed |
Could not complete — check failed_reason if present |
Invoice
One CFDI UUID for an entity. List endpoints return processed invoices only (is_processed = true): metadata plus parsed XML fields and aggregates.
type |
Role |
|---|---|
I |
Income invoice — PPD or PUE; receives payment aggregates |
E |
Credit note — may reduce a type I invoice |
P |
Payment complement — records payments against other UUIDs |
N |
Payroll |
T |
Transfer |
End-to-end data flow
sequenceDiagram
autonumber
participant App as Your app
participant API as Meefi API
participant Worker as Processing
participant SAT as SAT portal
App->>+API: POST /v1/extractions
API-->>-App: 201 { id, status: pending }
API->>+Worker: Enqueue extraction job
Worker->>Worker: status → running
Worker->>+SAT: CIEC login + list CFDI by month
SAT-->>-Worker: Metadata list
loop Each invoice in range
Worker->>SAT: Download XML / PDF
Worker->>Worker: Parse CFDI fields
Worker->>Worker: Store metadata + files
end
Worker->>Worker: Link payment complements → invoices
Worker->>Worker: Link credit notes → invoices
Worker->>Worker: Refresh paid / due / credited amounts
Worker->>Worker: status → finished
App->>+API: GET /v1/extractions/{id}
API-->>-App: 200 { status: finished }
App->>+API: GET /v1/entities/{id}/invoices
API-->>-App: 200 Invoice collectionPayment complements and missing invoices
A type P complement references type I invoices by UUID. If the original invoice is outside your extraction window, the payment is stored and linked automatically when that invoice is downloaded in a later extraction.
flowchart LR
P["Type P complement
references UUID X"]
I["Type I invoice
UUID X"]
Agg["Aggregates on invoice X
paid_amount · due_amount"]
P -->|"stored immediately"| Pending[(Pending link)]
Pending -->|"invoice X downloaded
in later extraction"| I
I --> Agg
P --> AggSee Extractions — Historical coverage.
Financial aggregates (type I, PPD)
| Field | Meaning |
|---|---|
due_amount |
Outstanding balance from the latest payment complement |
paid_amount |
Total paid so far |
last_payment_at |
Most recent payment date |
fully_paid_at |
Set when the invoice is fully paid |
credited_amount |
Sum of eligible linked credit notes |
subtotal_credited_amount |
Subtotal portion of those credit notes |
PUE invoices are paid at issuance; these fields stay empty.
Webhooks
When extraction status or entity credentials change, the API POSTs an event to your registered URLs.
| Event | When |
|---|---|
extraction.update |
Extraction starts, finishes, or fails |
entity.update |
Credential validation completes or status changes |
Deliveries include Authorization: Bearer {webhook.token}. Return 2xx quickly and handle retries idempotently.
API map
| Area | Prefix | Purpose |
|---|---|---|
| Entities | /v1/entities |
Register and manage RFC + CIEC |
| Extractions | /v1/extractions, /v1/entities/{id}/extractions |
Start and monitor downloads |
| Invoices | /v1/entities/{id}/invoices, /v1/invoices/{id} |
Query processed CFDI |
| Webhooks | /v1/webhooks |
Subscribe to events |
| Health | /up |
Service liveness (no auth) |
Request and response schemas: OpenAPI reference.
Recommended integration
sequenceDiagram
autonumber
participant App as Your app
participant API as Meefi API
App->>API: POST /entities
Note over App,API: Store entity id
loop Poll until valid
App->>API: GET /entities/{id}
end
App->>API: POST /extractions (12+ month backfill)
Note over App,API: Poll or webhook until finished
App->>API: POST /extractions (incremental sync)
App->>API: GET /entities/{id}/invoices?filters
App->>API: GET /invoices/{id}/cfdi