Prerequisites
-
A FIEL (e.firma) registered on the fiscal profile — descarga masiva authorizes with the FIEL,
not the CSD. Without one,
POST /v1/downloadsreturns 422download.fiel_required. - No sandbox exists for descarga masiva. Test mode uses the simulated driver; real downloads only work in production against a live FIEL.
Request a download
date_from/date_to accept YYYY-MM-DD or a full ISO datetime; a bare date widens to cover the
whole day. Response is a download object with status: "requested" and a metadata.warnings
array carrying any SAT-limit advisories. 201 for a new request, 200 if it deduped to an
identical prior request (no new SAT slot consumed).
Lifecycle
download.ready / download.failed webhooks instead of polling.
SAT limits — design around these
The SAT (not this API) enforces the following. They are the reason descarga masiva must be planned, not fired ad hoc. Codes below map tosat.* in ../errors.md.
| Limit | Code | What it means | What to do |
|---|---|---|---|
| 2 identical lifetime requests | 5002 sat.download_request_limit | You may request the exact same params at most twice — ever. | Never retry identical params. Vary/fragment the date range so each request is distinct. |
| 200,000 XML per request (1M metadata) | 5003 sat.download_too_large | The range produced too many documents. | Fragment the date range (month → weeks → days) and issue separate requests. |
| Package URLs expire ~5 min | 5007 sat.download_package_not_found | The signed S3 URL went stale before download. | Re-poll status to re-mint URLs and download at once (the poll job already does this). |
| No data | 5004 sat.download_no_data | Terminal success, empty result — the range has no CFDIs. | Do not retry; treat as done. Surfaces as status: "no_data". |
| Third party not authorized | 5001 sat.download_unauthorized | The FIEL does not match the requested RFC/side. | Ensure the FIEL belongs to the RFC and side matches its role. |
Fragmentation strategy
Because of both the 200k cap and the 2-identical-lifetime rule, prefer narrow, non-repeating windows:- Start monthly. If a month returns
5003(too large), split it into weeks, then days. - Make every request’s
date_from/date_tounique — do not resubmit a window you already requested twice. If you must reprocess, reuse the stored packages viaGET /v1/downloads/:id/filesrather than issuing a new SAT request. - For ongoing sync, advance the window forward (yesterday, the day before…) so params never repeat.
- Metadata requests are cheaper (1M cap) — pull
type: "metadata"first to size a range before pulling fulltype: "cfdi".
Notes
status_filter(active/cancelled) is recorded for request differentiation but is advisory — it is not currently forwarded to the SAT request.- The FIEL PFX is the only key material sent to the PAC, and only for descarga masiva. CSD private keys never leave this server.