Extractions
An extraction downloads CFDI from the SAT for a date range, parses the XML, links related documents, and updates invoice aggregates.
Lifecycle
stateDiagram-v2
[*] --> pending: POST /v1/extractions
pending --> running: Worker picks up job
running --> finished: All months processed
running --> failed: Unrecoverable error
failed --> running: Automatic retry
finished --> [*]Request and processing
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
{ entity_id, options.period }
API-->>-App: 201 { id, status: pending }
API->>Worker: Dispatch job
Worker->>Worker: status → running
API->>App: webhook extraction.update (running)
loop Each month in period
Worker->>+SAT: List CFDI metadata
SAT-->>-Worker: UUID list + status fields
Worker->>Worker: Upsert invoice metadata
Worker->>SAT: Download XML / PDF
Worker->>Worker: Parse & store fields
end
Worker->>Worker: Resolve payment → invoice links
Worker->>Worker: Recompute PPD aggregates
Worker->>Worker: status → finished
API->>App: webhook extraction.update (finished)
App->>+API: GET /v1/extractions/{id}
API-->>-App: 200 { status: finished }Extraction object
| Field | Type | Description |
|---|---|---|
id |
UUID | Extraction ID |
status |
string | pending, running, finished, failed |
tries |
integer | Number of processing attempts |
entity |
object | Nested entity summary (id, tax_id, name) |
options |
object | Request options (period, download type) |
started_at |
datetime | When processing started |
finished_at |
datetime | When processing completed or failed |
created_at |
datetime | When the extraction was created |
Start an extraction
POST /v1/extractions
{
"entity_id": "9e08bb63-f6c1-44cf-a5b5-a92967cb172d",
"options": {
"period": {
"from": "2026-01-01",
"to": "2026-06-03"
},
"download_type": "issued"
}
}
Options
| Field | Type | Description |
|---|---|---|
options.period.from |
date | Start of date range (inclusive) |
options.period.to |
date | End of date range (inclusive) |
options.download_type |
string | issued (default) or received |
Long date ranges are processed month by month against the SAT.
Returns 201 Created. Processing is asynchronous — poll or use webhooks.
Monitor progress
GET /v1/extractions/{id}
Poll until status is finished or failed. Alternatively, subscribe to extraction.update webhooks.
List extractions for an entity
GET /v1/entities/{entity_id}/extractions?per_page=50
Returns paginated extractions ordered by newest first.
What happens during an extraction
- Authenticate to the SAT with the entity CIEC
- List CFDI metadata for each month in the period
- Download and parse XML and PDF files
- Link payment complements to their target invoices
- Link credit notes to related invoices
- Refresh
paid_amount,due_amount, andcredited_amounton affected invoices
Re-running an extraction for the same period is safe and produces consistent results.
Historical coverage
Payment complements (type P) reference UUIDs of original invoices (type I). If you only extract recent months:
- Complements download successfully
- Payment data is stored against the target UUID
- Aggregates on the target invoice update once that invoice is included in a later extraction with an earlier date range
flowchart TD
A["Day 1: Extract last 30 days"] --> B["Type P complements arrive"]
B --> C["Payments stored · UUID link pending"]
C --> D["Day 7: Backfill 12 months"]
D --> E["Type I originals downloaded"]
E --> F["Aggregates refreshed on invoice"]Recommendation: run a wide initial backfill (12+ months), then incremental syncs.
Retries and failures
Failed extractions are retried automatically. Common causes:
- Invalid or expired CIEC (
credential_status: invalid) - SAT connectivity or availability issues
When status is failed, check failed_reason on the extraction resource.
Webhook events
Status transitions emit extraction.update with the latest extraction object in the payload.