Skip to main content
Download all your issued and received CFDI invoices directly from SAT using your FIEL (Firma Electrónica Avanzada). Descarga Masiva gives you a complete history of every invoice associated with your RFC — whether you issued it in gigstack or not.

Overview

The Descarga Masiva API lets you connect your RFC to SAT’s bulk download service and retrieve your full invoice history. You can run one-time requests for specific date ranges, or set up a daily schedule that automatically syncs new invoices.

Key Features

  • Full Invoice History - Download all issued and received CFDIs from SAT, regardless of origin
  • Automatic Daily Sync - Schedule recurring downloads to keep your data up to date
  • FIEL Authentication - Secure connection using your electronic signature (FIEL)
  • Live Status Updates - Status polling refreshes pending requests in real time
  • Metered Billing - Pay only for what you download ($0.20 MXN per XML)

Prerequisites

Before using Descarga Masiva:
  1. Your team must have a valid RFC configured — and it must be the same RFC the FIEL belongs to. See Step 3; this is the single most common way onboarding fails.
  2. You need an active paid gigstack plan
  3. You must have your FIEL files (.cer + .key) and their password ready
FIEL vs CSD: The FIEL (Firma Electrónica Avanzada) is your personal digital identity certificate used to authenticate with SAT. It is different from the CSD (Certificado de Sello Digital), which is used to stamp CFDI invoices. You need both for full gigstack functionality.

Setup Flow

Step 1 — Check Activation Status

Before anything else, check whether Descarga Masiva is activated for your team.
Response:
Status values:

Step 2 — Activate

Response:
Billing:
  • If your plan includes Descarga Masiva (type: "included"): activation is free — you only pay $0.20 MXN per XML downloaded.
  • If activating as an add-on (type: "addon"): also 0.20MXNperXMLdownloaded.Thereisnomonthlybasefee—theformer0.20 MXN per XML downloaded. There is no monthly base fee — the former 400 MXN/RFC/month charge was removed, and pricing.addonMonthly now returns null.

Step 3 — Upload your FIEL

This is the main setup step. Upload your .cer and .key files along with the password. gigstack validates your FIEL, securely stores the credentials, and automatically registers your RFC with SAT — all in one request.

⚠️ Read this before you upload: the FIEL’s RFC must equal the team’s RFC

The upload is rejected with 400 "RFC mismatch" unless the RFC inside the .cer is exactly the rfc stored on the team being addressed by the request. The error names both values:
Three consequences worth internalizing:
  1. The team that matters is the one in ?team=, not the master team. Under gigstack Connect the request resolves against the connected team named by the query parameter. Uploading a connected client’s FIEL while pointed at your master team fails, and uploading with ?team= set to a connected team whose RFC differs from the certificate fails too.
  2. Each RFC requires its own team. There is no way to attach a second RFC to an existing team. One RFC ⇄ one team, always.
  3. A company FIEL cannot go on a team created with an individual’s RFC. A persona moral RFC is 12 characters; a persona física RFC is 13. If the team was created with the legal representative’s personal RFC and the FIEL is the company’s, every upload attempt will fail — and there is no way to fix it from this endpoint.
Practical rule: create the team with the RFC that the FIEL will belong to. For a business that is the business RFC, not the RFC of the director, the accountant, or whoever happens to hold the e-firma. This is decided at team creation (POST /v2/teams, or the rfc field of POST /v2/auth/signup) — long before anyone touches a certificate — which is exactly why it goes wrong: the mistake surfaces only here, at the very end of onboarding, after credentials have already been collected from the client. Verify the RFC on the team before asking anyone for their FIEL.
Parameters: Query parameters:
sync_start_date is not accepted. The historical sync window is always set to the maximum SAT allows (71 months back); sending the field has no effect.
Other 400 responses from this endpoint, all with success: false: Response:
When registered: true, your RFC is connected to SAT and you can start downloading invoices immediately. Registration only runs when you send phone. Without it the credentials are still stored, but the response comes back with registered: false and you must call POST /v2/invoices/download/register yourself. With phone present and registration failing (rare — usually a temporary SAT/PAC service issue) the message says so explicitly; retry with the same register endpoint. Re-uploading a renewed FIEL is safe: the certificate fields are updated in place and the team’s Descarga Masiva activation and download schedule are preserved.

Connecting via API (PFX)

If you already have a PFX file (PKCS#12) — for example, one you generated programmatically or from a previous export — you can connect your FIEL directly using a JSON body instead of uploading .cer + .key files.
One team per RFC. gigstack connects one RFC per team. If you need to manage multiple RFCs (e.g. for different legal entities), create a separate gigstack team for each RFC. The same RFC check applies here. The RFC inside the PFX must equal the rfc on the team being addressed — the ?team= target under Connect, otherwise the API key’s own team — or the call returns 400 "RFC mismatch". See the box in Step 3: a company FIEL cannot be attached to a team created with an individual’s RFC, and the only fix is a team whose RFC matches. This endpoint takes the registration phone from the team’s supportPhone (falling back to a generic number), so there is no phone field to send.
Parameters: Response:
The sync start date is always set to the maximum allowed window (71 months back) — it is not configurable via this endpoint. If registered: false, registration with SAT failed. Use POST /v2/invoices/download/register to retry.

Downloading Invoices

Once activated and registered, you have two options: scheduled daily sync or manual requests.

Option A — Scheduled Daily Sync

Set up a schedule and gigstack automatically downloads new invoices every day.
Parameters: Response:
To check your current schedule configuration and FIEL status:

Option B — Manual Download Request

Submit a request for a specific date range. SAT processes it asynchronously.
Parameters:
Date range: the SAT limits each request to one month, so gigstack splits the range into one request per calendar month. Months that already have a pending request are not submitted again.
Response:
created holds the ids of the new requests (use them with GET /v2/invoices/download/status/:request_id); duplicates holds ids of identical requests already pending; duplicate is true when every month was already pending. At most 10 manual requests per team per day are accepted (429 rate_limit_exceeded).

Tracking Request Status

Check the status of your download history — pending requests are updated in real time:
Response:
Status values:

Checking a Single Request

Returns the SAT status of one request (status: pending, accepted, processing, completed, failed, expired), invoice_count, and — once completed — packages, a list of { "id", "index" }. Download each package with:
The ZIP comes back base64-encoded inside JSON (data.content, with content_type: "application/zip" and encoding: "base64"), not as a binary download. Packages expire after a period set by the SAT, so download them promptly. To fetch one CFDI’s XML from the SAT without a bulk request, use GET /v2/invoices/download/invoice/:uuid.

Preview a Range, Then Import Selectively

Reading CFDI metadata from the SAT is free; only downloading an XML is billed. Use that to see what a date range contains before paying for anything.

1. Preview

directions defaults to received only. The call answers 202 with a job id (satjob_…, status: "queued"): one month takes about twelve seconds at the SAT, so the work runs in the background. Only one job may run per team at a time (409 otherwise).

2. Follow the job

The CFDIs found are stored as rows in the metadata stage. List them with GET /v2/invoices/sat?sync_state=metadata.

3. Import the XMLs you want

This is the billed call: $0.20 MXN per XML, charged once per CFDI.
  • Up to 500 UUIDs per call.
  • The server always computes the cost itself. If you send confirm_cost_mxn and it does not match, the call returns 409 instead of charging a different amount. Above 100 invoices, confirm_cost_mxn is required.
  • UUIDs that cannot be imported are listed in skipped with a reason: not_found, wrong_team, already_imported, already_queued, is_nomina (nómina XMLs contain employee data and are never downloadable) or not_importable.
The response reports queued, estimated_cost_mxn and skipped. Each XML that arrives triggers a sat.invoice.synced webhook.

Sync Progress

The SAT hands over your history in month-sized windows, starting at your sync start date. Until the backfill reaches the present, a query for recent dates succeeds but returns nothing — which looks exactly like having no invoices. This endpoint tells the two apart. The values live under data.provider, which is null until the first background refresh: Pass ?refresh=true to recompute now (takes a few seconds).

Sync configuration and troubleshooting

  • GET /v2/invoices/download/schedule — the current schedule plus setup status: fiel_uploaded, registered, registered_at, sat_completed, and FIEL certificate metadata (RFC, expiry, serial number).
  • PUT /v2/invoices/download/sync-period — re-registers the team so the provider syncs from the earliest date allowed. The body is ignored; the start date is always computed by gigstack. Requires a team RFC, a prior registration, stored FIEL credentials and a phone number on the FIEL record.
  • POST /v2/invoices/download/enable-sync — lower-level switch that turns automatic sync on. In most cases, configure the schedule (PUT /v2/invoices/download/schedule) instead.
  • GET /v2/invoices/download/debug — FIEL, registration, schedule and SAT connectivity details for troubleshooting.

Deactivation

To stop Descarga Masiva and remove billing:
Scheduled downloads stop immediately. If the feature was billed as an add-on, the charge is removed from your subscription (prorated). Any XML downloads already recorded in the current period are still billed at period end.

Common Errors



Browsing Downloaded Invoices

Once invoices are downloaded and saved, retrieve them with:

List SAT Invoices

Query Parameters: Response:

Get a Single SAT Invoice


Retry an XML Download

Retries the XML download for a received SAT invoice stuck in processing or error. If the XML is already stored, it answers 200 with message: "Invoice already has XML downloaded." and charges nothing. A successful retry triggers a sat.invoice.synced webhook with retried: true.

Generate a PDF

Generates a PDF from the stored XML of a received SAT invoice (the XML must have been downloaded). The result is cached. The response is not enveloped: it is { "pdf": "<base64>" }.

Import XMLs You Already Have

Uploads up to 50 stamped CFDI XMLs you already hold (from the SAT portal, a supplier, another system). Free, and it needs no FIEL or Descarga Masiva activation. Not to be confused with POST /v2/invoices/download/import, which fetches XMLs from the SAT and is billed. Each XML is filed by your team’s RFC:
  • Your RFC is the issuer → stored as an invoice, readable with GET /v2/invoices/:id.
  • Your RFC is the receiver → stored with your received SAT invoices (GET /v2/invoices/sat), already imported, so Descarga Masiva will never download or bill it.
  • Neither → rejected, nothing is written.
Send each file as xml (text) or content (base64):
Each result carries action: created, completed (filled a Descarga Masiva row that was missing its XML), already_exists, conflict (the UUID belongs to another account) or rejected, plus direction (issued / received). Received nómina XMLs are rejected because they contain employee personal data. Status is stored as Vigente: an XML cannot show a later cancellation.

Full Endpoint Reference