Skip to main content
Register a taxpayer’s RFC once. We backfill their CFDI history from the SAT — up to the full 71-month window — and then keep it current, automatically. You get every CFDI the SAT holds for that RFC: the ones they issued, and the ones they received from their suppliers. This is a different thing from /v1/invoices. An invoice is a CFDI you stamped through this API. A sat_document is any CFDI the SAT has on file for that RFC — including a supplier’s invoice to the taxpayer, and everything they issued long before they ever integrated with you. It is also different from massive download: that is an on-demand pull for one date range, hemmed in by hard SAT limits. This is a standing sync you turn on once.

1. Attach a FIEL

Sync authorizes with the taxpayer’s FIEL (e.firma) — not the CSD. Attach it to the fiscal profile (fiel_cer, fiel_key, fiel_password); without one you get 422 sync.fiel_required.

2. Turn sync on

Enabling is idempotent — re-enabling an already-registered RFC is a no-op, not an error. The backfill runs in the background, chunk by chunk. Six years of history is many small jobs, not one enormous request, so it makes steady progress rather than timing out.

3. Read the documents

Filter by fiscal_profile_id, side (issued / received), and status (vigente / cancelado); cursor-paginate with starting_after. Each row carries the folio fiscal (uuid), both parties, total, subtotal, type, serie/folio, and the SAT status. Cancellations flow through: if a CFDI you already mirrored is cancelled later, the next sync flips its status to cancelado and fills cancelled_at on the same row.

Freshness: expect 1–3 days, and we tell you exactly

synced_through is the honest watermark — we have your CFDIs up to and including this date. lag_days is how far that trails today. A healthy sync sits 1–3 days behind, and that floor cannot be beaten. It is not our latency: the SAT itself does not publish a CFDI to its bulk-download service until roughly 24–72 hours after it is issued. Any vendor claiming real-time SAT data for received invoices is describing something the SAT does not offer. So: use /v1/invoices for the CFDIs you stamp (those are immediate). Use SAT sync for the complete fiscal picture, and read synced_through before you reconcile a period.

Health: enabled is not the same as working

The upstream sync can stop silently. When the SAT rejects one of its requests, it stops fetching for that RFC and does not recover on its own — while still reporting itself as enabled. Left alone, a taxpayer’s data simply stops updating and nothing says so. We watch the watermark instead of the flag. If it stops advancing, we mark the profile stalled, attempt an automatic repair, and fire a webhook:
Subscribe to fiscal_profile.sync_stalled. It is the only warning that a taxpayer’s fiscal data has quietly gone stale.

When the automatic repair is not enough: an expired FIEL

The most common cause of a permanent stall is an expired or revoked e.firma. This one is nasty, and worth understanding:
  • A FIEL is not validated when you register it. Registration succeeds with a dead certificate.
  • The failure only appears later, when the SAT rejects the data requests.
  • The result looks identical to a transient stall — except no repair fixes it.
The signature is a sync that ran fine for a long time and then froze on a specific date, with every subsequent request rejected. An e.firma is valid about four years, so this tends to hit taxpayers who registered a while ago. The fix is a renewed e.firma — the taxpayer renews it at the SAT, you attach the new .cer/.key to the fiscal profile, and then call POST /v1/fiscal_profiles/:id/sync again. Re-enabling pushes the renewed certificate to the sync service (it does not just re-toggle), so the nightly job recovers on its next run. No amount of retrying the old certificate will substitute. If a profile stays stalled after a repair attempt, check the certificate’s validity before anything else.

Status reference

Turning it off

Already-mirrored documents are kept; nothing new is pulled.

Next