Skip to main content
Download the CFDIs (Mexican electronic invoices) an RFC issued or received in a date range, as a ZIP of XML files. You never choose: POST /v1/downloads is the same request either way. Live downloads with a SAT password need a subscription; test mode does not.

Pricing

Downloads with a SAT password are charged on top of your plan. Prices are in MXN with IVA included. An RFC is active in a month when it receives at least one delivered XML that month, on the Mexico City calendar. You pay for it once that month, however many downloads you make. On Growth and Scale, active RFCs get cheaper as you add them. Each RFC pays its own step’s rate, so adding an RFC never lowers the bill: For example, 30 active RFCs on Growth cost 9 × $114.84 + 15 × $91.64 + 6 × $68.44 = **$2,818.80 MXN**. Subscriptions renew on the 1st of each month, so the steps count one calendar month. GET /v1/billing returns your plan’s steps in sat_active_rfc_tiers. You pay for each invoice once. An invoice an earlier download already delivered for that RFC and side is skipped and not charged again, even if the new date range is different. Example: 500 XMLs for one RFC in a month cost 500 × $0.696 = $348.00, plus $114.84 for the active RFC: **$462.84 MXN** with IVA. Failed downloads and downloads with no invoices are free, and test mode is free. Usage appears on your plan’s invoice. GET /v1/billing shows the XMLs and active RFCs so far this month.
Test mode is simulated. With a sk_test_ key nothing reaches the SAT. A download finishes about 30 seconds after you request it and contains sample XMLs, not real invoices. The year of date_from picks the outcome, and those years ignore the date limits below:

From request to XML files

This works as written with a test key and any test fiscal profile.
1. Save the SAT password. A test key verifies it immediately. With a live key, wait for the fiscal_profile.sat_credential_verified webhook (details).
2. Request the download. side is issued (the RFC is the issuer) or received.
That is a 201. Sending the same request again returns the same download with 200, with no new charge. See Asking again for when a repeat fetches new invoices. 3. Wait for it to finish. Live downloads usually take minutes and can take 40 minutes or more. Subscribe to download.ready, download.partial, download.no_data and download.failed webhooks, or poll:
4. Fetch the files. GET /v1/downloads/:id/files lists every ZIP.

Partial results

partial means some invoices arrived and some did not. The ZIP holds what we got, and it is not the whole range. download.partial fires instead of download.ready, and result has the counts:
See what is missing. The report is a CSV. Rows with status error or not_checked were not delivered, and the error column says why.
Get the rest. Send the same POST /v1/downloads again. You get a new download (201) with continued_from set to the previous id, containing only invoices you do not have yet. Keep the files from both. An invoice the SAT will not release stays in the report as error.

Asking again

It is safe to send a request more than once, and safe for date ranges to overlap, so you can pull “month to date” every day. A range stays open for 4 days after it ends because an invoice can reach the SAT up to 72 hours after its date. Test mode does not simulate skipping: a new test download always contains sample XMLs. A new download holds only what is new, so keep the files from each one. Skipped invoices are counted in result.already_delivered, and continued_from points to the earlier download of the same dates. If nothing is new, the download ends as no_data, with no ZIP and no charge.

Limits with a SAT password

Requests are never split automatically, because that would spend the daily limit without telling you.

Statuses

Common errors

Every code is in the error reference.

FIEL details

A FIEL saved as the SAT credential behaves exactly like a saved SAT password. Without a saved credential the profile uses its FIEL, added with PATCH /v1/fiscal_profiles/:id. The SAT allows 2 identical requests, ever (sat.download_request_limit), so never repeat exact parameters, and 200,000 XMLs per request (sat.download_too_large), so split wide ranges by month, week, then day. type: "metadata" returns an index without XML files, useful for sizing a range. For an ongoing feed instead of one-off pulls, see SAT sync.