Home / Blog / Tutorials / CFDI SAT 2026 — real operations
TutorialsMexico

CFDI SAT 2026: Mexico's real-operations reform — Odoo playbook

Since January 1, 2026, any CFDI issued without supporting documentation is a simulated operation and a criminal tax offense.
Here's what changes for SMBs on Odoo: what l10n_mx covers, where the gaps live, and how to restore your CSD if SAT already suspended it.

Sergei Filatov
Sergei FilatovFounder · data-metrics.pro · May 25, 2026
◷ 13 min read

One-minute summary

At 00:00 on January 1, 2026, Mexico's tax authority flipped a switch. Every CFDI issued by a Mexican SMB must now reflect real and verifiable operations — or it stops being a paperwork mistake and becomes a criminal tax offense under Article 113 Bis of the Federal Fiscal Code. If you run a business in Mexico on Odoo and you think the CFDI SAT 2026 reform is about updating an XSD schema, the next 14 minutes will disappoint and save you in equal measure.

  • January 1, 2026 activated the real-operations rule: a CFDI without supporting documentation at the moment of issuance counts as a simulated operation and falls under Art. 113 Bis CFF.
  • January 30, 2026 published the updated CFDI 4.0 catalogs (c_UsoCFDIc_FormaPago, adjustments to c_RegimenFiscal). PACs now reject the old codes.
  • CSD suspension under Art. 17-H Bis CFF kicks in for issuance without materiality, mass invoicing, prolonged inactivity, missed filings, and irregular hydrocarbon operations. Restoration goes through the Aclaración procedure; SAT has up to 40 business days to resolve.
  • Cancellation gives the recipient 3 business days to accept or reject through Buzón Tributario; silence equals acceptance. Reasons 01 through 04 are mandatory, and reason 01 requires a substitute CFDI with the UUID in CfdiRelacionados.
  • Fines for missing or invalid CFDIs are indexed annually in the RMF and add up to tens of thousands of pesos per document.
  • Odoo l10n_mx covers issuance, cancellation, the payment complement, and Carta Porte 3.1 out of the box. The real-operations audit trail needs a custom module of 40–80 development hours or a disciplined workflow built around mandatory attachments.
!
Art. 113 Bis CFF reaches up to 9 years of prison when the issuance is systematic (Art. 113 Ter). This is not an administrative risk; it is criminal liability for the legal representative and the accountant. Before going further, audit the actual issuance flow, not just the technical configuration.

Context and 2026 timeline

CFDI 4.0 became mandatory for every Mexican taxpayer on April 1, 2023, replacing CFDI 3.3. The XML format has not changed since — what changes every year is the validation layer on top. The 2026 SAT reform is not a new format. It's a new enforcement layer.

#1. What came before

Until 2026, SAT used Art. 69-B CFF to publish lists of EFOS (companies issuing simulated operations) and EDOS (companies deducting them) in the Federal Official Gazette. Since 2024, those lists grew quickly — each quarter the DOF added hundreds of new RFCs into definitive presumption. But the procedure was slow: SAT published the presumption, granted 15 days to respond, and absent reaction moved it to definitive status. Fiscal litigation came separately.

#2. What changes in 2026

The 2026 fiscal reform made two structural changes:

  1. Materiality required at the moment of CFDI issuance. Before, SAT proved non-existence after the fact — once the EFOS list was published. Now the taxpayer must hold the proof of materiality at the time of issuance: a contract, an accounting entry, supporting documentation, and evidence of delivery of the good or service.
  2. Penalty escalation to the criminal plane. A false CFDI is no longer an administrative error that can be fixed through a clarification request. It now carries potential criminal liability under Art. 113 Bis CFF (2 to 9 years of prison) or 113 Ter when the issuance is systematic.

#3. Key dates for the 2026 fiscal year

DateEventAction
Jan 1, 2026Real-operations rule takes effectAudit the CFDI issuance flow and supporting documentation
Jan 30, 2026Updated CFDI 4.0 catalogs (published Jan 29)Update l10n_mx to the latest release; check the PAC cron
Apr 1, 2026End of the Carta Porte 3.1 grace periodEvery transport CFDI must include the 3.1 complement
~Jul 1, 2026Expected mid-year RMF amendmentsSubscribe to the DOF and to SAT communications
ContinuousSAT publishes EFOS/EDOS lists quarterlyCross-check customers and suppliers each quarter

#4. Regulatory reference frame

  • Art. 29 CFF — duty to issue a CFDI.
  • Art. 29-A CFF — CFDI content requirements and cancellation procedure.
  • Art. 17-H Bis CFF — grounds and procedure for CSD suspension.
  • Art. 69-B CFF — presumption-of-non-existence procedure (EFOS / EDOS).
  • Art. 113 Bis CFF — criminal typification for issuing or selling CFDIs without real operations.
  • Art. 113 Ter CFF — aggravated charge when the issuance is systematic.
  • Arts. 42 and 49 CFF — verification powers, on-site visits, and reviews.
  • Arts. 81 and 82 CFF — administrative fines.

For the exact fine range and the cross-reference to Annex 5 of the RMF, consult the current DOF publication: amounts are reindexed each year by UMA. For deeper regulatory context, see the Odoo in Mexico pillar guide.

Technical requirements: an Odoo compliance walkthrough

The technical stack for CFDI 2026 is not exotic. The hard part is not installing modules — it's disciplining the workflow so every CFDI leaves a materiality trail. Below are the five steps that cover roughly 90% of the configuration work in Odoo 17 and Odoo 18.

#1. l10n_mx localization — what must be installed

The minimum stack for compliance in Odoo 17 and 18:

l10n_mx                       # Mexico base localization
l10n_mx_edi                   # CFDI 4.0 emission + cancellation
l10n_mx_edi_40                # CFDI 4.0 schema + validations
l10n_mx_edi_extended          # Payment complement (REP)
l10n_mx_edi_payment           # Payment complement workflow
l10n_mx_edi_landing           # Foreign trade (export)
l10n_mx_edi_carta_porte       # Carta Porte 3.1 (transport)
l10n_mx_reports               # DIOT, ISR withholdings

It is part of the OCA bundle and the Vauxoo-maintained branches. Odoo Enterprise ships most of it included; Community needs the OCA/l10n-mexico and Vauxoo/odoo-l10n-mexico repos. Vauxoo is the HQ partner for Mexico and contributes most of the upstream work in l10n_mx.

#2. PAC configuration

A PAC (Authorized Certification Provider) is a SAT-authorized provider that stamps the CFDI and submits it for registration. Odoo l10n_mx supports SW Sapien, Solución Factible, Diverza, Edicom Mexico, and Facturama out of the box.

Configuration sequence:

  1. Settings → Companies → select the company → Tax Configuration → PAC selection.
  2. Upload the CSDthe .cer and .key files plus the password of the Digital Seal Certificate issued by SAT.
  3. Set RFCRégimen Fiscaland Lugar de Expedición (5-digit postal code).
  4. Link it to the invoice journals (F-B-P- for payments).
  5. Enable the cron l10n_mx_edi.cron_update_cfdi_status every 6 hours.
!
The CSD loaded into Odoo must match the active CSD at SAT. If SAT suspends the CSD, Odoo keeps trying to stamp, gets rejections, and the invoice stays in posted with an empty UUID. Without an alert, you only discover the problem at month-end when 60 invoices are already stuck.

#3. CFDI issuance workflow with real-operations support

Odoo's standard flow:

Sale Order → Delivery → Invoice → CFDI emission → PAC stamps → XML/PDF

Under the 2026 reform, each step must leave an audit trail:

  • Sale Order — contract or PO from the customer as an attachment.
  • Delivery — signed delivery note (photo or scanned PDF).
  • Invoice — amount congruence between order and invoice.
  • CFDI XML — correct UsoCFDIFormaPagoMetodoPago, and régimen.

Vanilla Odoo doesn't complete the audit trail. Extend it with a custom module:

class AccountMove(models.Model):
    _inherit = 'account.move'

    materialidad_soporte_ids = fields.Many2many(
        'ir.attachment',
        string='Materiality Support',
        help='Documents proving the reality of the operation (Art. 113 Bis CFF)')

    @api.constrains('state', 'materialidad_soporte_ids')
    def _check_materialidad_mx(self):
        for move in self:
            if (move.state == 'posted'
                    and move.move_type == 'out_invoice'
                    and move.country_code == 'MX'
                    and not move.materialidad_soporte_ids):
                raise ValidationError(
                    'CFDI cannot be issued without materiality support.')

This code blocks posting any invoice that doesn't carry at least one attached document. In practice it rewrites the entire team discipline: the accountant physically cannot issue a CFDI \"on trust\".

#4. Cancellation workflow — the 3-day window

Since 2022, cancellation requires choosing a reason:

  • 01 — Invoices with errors, with relationship: requires the UUID of the substitute CFDI.
  • 02 — Invoices with errors, without relationship.
  • 03 — The operation did not take place.
  • 04 — Nominative operation linked to a global invoice.

In Odoo l10n_mx 17 and 18, the cancellation flow runs through l10n_mx_edi.action_cancel. The recipient receives the notice in Buzón Tributario and has 3 business days to accept or reject. No reply means automatic acceptance.

Odoo gap: the system does not track the 3-day timer automatically. A custom cron must sync the status through SAT's consultarEstatusCFDI — otherwise, a week later the company doesn't know which cancellations actually went through.

#5. CSD suspension — what to do once you're blocked

If SAT suspends the CSD under Art. 17-H Bis:

  1. Sign in to Portal SAT → Servicios → Aclaraciones → \"Aclaración sobre dejar sin efectos el CSD\".
  2. Upload evidence: analytical accounting, contracts, bank statements, materiality proof for each suspect CFDI.
  3. SAT has up to 40 business days to rule.
  4. In parallel inside Odoo: stop CFDI issuance with the flag company_id.l10n_mx_edi_cfdi_block = True or temporarily lock the journal.
  5. Keep every pending invoice in draft, do not post — otherwise they hang in to_send and create reconciliation chaos once the CSD is restored.

If your company is already in suspension, the Odoo project rescue service is the right call: it combines the SAT clarification with the technical discipline that prevents a repeat.

When Odoo l10n_mx fits and when it doesn't

Not every Mexican business model fits Odoo l10n_mx. Six typical cases and where the line is defensible — or where it makes more sense to move to a different stack.

#1. Strong fit: 10–50-person SMB, B2B with standard goods

An IT-equipment distributor in Querétaro, 28 people, ~2,000 CFDIs/month. Every CFDI is tied to a sale order, which in turn is tied to a signed quote in PDF. Materiality is obvious and audit-friendly. Odoo l10n_mx plus a custom module for mandatory attachments covers 100% of the workflow.

#2. Strong fit: services on monthly retainer

A marketing agency in Mexico City with 15 retainer clients. One CFDI per month per client. The contract sits as an attachment on the partner record, the timesheet is a monthly report. UsoCFDI G03 (general expenses). Transparent congruence. The only custom piece is exporting the timesheet as a mandatory attachment.

#3. Partial fit: marketplace sellers (Mercado Libre, Amazon MX)

A Mercado Libre seller, 500 to 3,000 sales/month. The marketplace does not pass the buyer's RFC for retail. The workaround is a global invoice with cancellation reason 04. Odoo l10n_mx supports the global invoice but requires custom consolidation of orders into a single CFDI with each related UUID. Materiality for retail gets proven by delivery confirmation from the marketplace — that is external data, Odoo doesn't pull it on its own. You need a webhook integration or a daily CSV import.

#4. Doesn't work out of the box: restaurant chain with on-demand invoices

A 6-location QSR chain in Monterrey, 1,500 transactions/day. Only 8 to 12% of customers request an invoice. The POS issues a ticket; the customer later enters their RFC on a web form and receives the CFDI. Materiality between ticket and issuance crosses 24 to 48 hours. SAT can question it if the ticket gets lost. You need POS → ticket archive → invoice emission with automatic linking. That's a custom module of 80 to 120 hours, or a specialized POS with SAT integration instead of Odoo POS.

#5. Doesn't work: hydrocarbons and other regulated sectors

A fuel or LPG distributor, regulated sector. Art. 17-H Bis CFF gives SAT reinforced grounds for CSD suspension precisely in these sectors, plus mandatory complements (Hydrocarbons, IEPS) that must correlate permanently with customs declarations. l10n_mx_edi_extended plus a custom hydrocarbons complement works in theory; in practice, for an SMB in this sector, it's more economical to use specialized compliance software (Edicom, GoSocket) and integrate it with Odoo through a middle layer.

#6. Special case: USMCA / cross-border (United States, Canada)

An SMB exporter to the United States, CFDI with the Foreign Trade 1.1 complementThe 2026 reform doesn't change the complement, but adds the materiality requirement per shipment. You need a link between the CFDI, the customs declaration, and the shipping documentation. l10n_mx_edi_landingdelivery_landed_costs + a custom field for the pedimento — workable, but it demands disciplined data entry from the logistics team.

The 5 errors SAT catches most often

From field experience and from every formal clarification we've worked: these five patterns trigger about 70% of CSD suspensions in Mexican SMBs. Each one has a concrete fix in Odoo.

#1. CFDI issued with no supporting documentation

What happens. The company issues a CFDI \"just in case\" expecting the contract to come later. During an on-site visit under Art. 42 CFF, SAT asks for the contract — there is none.

Consequence. The CFDI is flagged as presumably without materiality. If the pattern repeats, SAT moves the RFC into Art. 69-B presumption and publishes it in the DOF.

How to avoid it in Odoo. Mandatory-attachment policy through custom validation (see Step 3). The sale order does not close without a signed PDF from the customer.

#2. Cancellation with reason 01 and no substitute

What happens. The accountant cancels a CFDI with reason 01 (\"errors with relationship\") but does not issue the substitute CFDI with the correct UUID in CfdiRelacionados. The PAC accepts the cancellation, but on audit SAT spots the gap.

Consequence. The cancellation gets reclassified as a simulated operation. Creditable VAT recovery on the recipient side becomes impossible.

How to avoid it in Odoo. Don't use reason 01 without simultaneously creating the substitute invoice through account.move.action_substitute_cfdi. A custom workflow blocks cancellation until the substitute is issued.

#3. CSD not refreshed in Odoo after rotation at SAT

What happens. The company obtained a new CSD at SAT, but the PAC config in Odoo still holds the old one. Odoo keeps stamping with an expired CSD — gets rejections, but the invoice stays posted with empty UUID.

Consequence. A series of \"invisible\" invoices that never reached SAT. On cross-check between the ledger and SAT a gap appears. In the worst case, this becomes a presumption of double bookkeeping.

How to avoid it in Odoo. Monitoring through the cron l10n_mx_edi.cron_update_cfdi_status every 6 hours. Email alert if 3 or more invoices stay in to_send for more than 24 hours. Quarterly CSD rotation with a calendar reminder.

#4. Wrong UsoCFDI

What happens. The customer provides their RFC and Odoo defaults to G03 (general expenses) on every CFDI. But the customer is an individual without business activity, for whom the correct UsoCFDI would be S01 (no fiscal effect) or another code per their régimen.

Consequence. The recipient tries to deduct a CFDI that is incorrect for their régimen. SAT spots the mismatch in cross-check. The recipient rejects the CFDI; in Odoo you need to cancel and re-issue.

How to avoid it in Odoo. UsoCFDI must be stored per partner and validated through l10n_mx_cfdi_usage_mapping against SAT's API at issuance time. The alternative is training sales to capture the correct UsoCFDI from the customer at onboarding.

#5. Carta Porte with no matching revenue CFDI

What happens. The transport company issues a Carta Porte 3.1 for a delivery but does not issue the matching revenue CFDI in the same fiscal period.

Consequence. SAT sees movement without matching revenue. Presumption of simulation or omission of income.

How to avoid it in Odoo. Inside l10n_mx_edi_carta_porte, add a custom cron that verifies the match between Carta Porte and revenue CFDI within the same fiscal period. A mismatch triggers an email to the accountant.

Anonymous case: how a Guadalajara SMB restored its CSD in 32 days

Situation. An electronics distributor SMB in Guadalajara, 18 people, annual revenue ~$45M MXN. Odoo Enterprise 17 with l10n_mx, implementation done in 2023 by a local Silver partner.

In March 2026, SAT suspended the CSD under Art. 17-H Bis: \"issuance of CFDIs without proof of materiality.\" The trigger was a mismatch between revenue CFDIs issued (~$3.2M MXN in February) and the DIOT (minimal creditable VAT supported by source documents).

What the internal audit found. The accountant issued \"rushed\" CFDIs for customers who asked over WhatsApp, with no sale order and no contract attachment. ~400 CFDIs in 6 months with no supporting documentation. Materiality existed (goods were actually delivered) but was not documented to audit grade.

What they did in 32 days.

  1. Days 1-3. Froze pending CFDI emission in Odoo (company.l10n_mx_edi_cfdi_block = True). Stopped all new invoice posting.
  2. Days 4-10. Ran a full audit of all 400 \"rushed\" CFDIs. For each one they looked for: bank statement (proving payment received), delivery note or photo of the shipment, email or WhatsApp message with the order. 287 of 400 had reconstructible materiality.
  3. Days 11-15. For the 113 CFDIs without reconstructible materiality — cancellation with reason 02 (\"no relationship\"), no substitute. Prepared the dossier for SAT acknowledging the error and laying out the remediation plan.
  4. Days 16-20. Installed the custom module in Odoo that blocks invoice posting without mandatory materialidad_soporte_ids. Trained the accountant and the sales team on the new workflow.
  5. Days 21-25. Filed Aclaración on Portal SAT. Uploaded the dossier with the 287 reconstructed materialities, the corrective plan, and Odoo partner certification of the mandatory-attachment workflow.
  6. Days 26-32. SAT reviewed. CSD restored on day 32.
When the CSD got suspended, invoicing dropped to zero. The first instinct was to blame the Odoo partner, but the problem wasn't technical — it was that the accountant kept issuing CFDIs without a contract. The mandatory-attachment custom module isn't defense against SAT: it's defense against ourselves.

Result. CSD restored, the business kept operating. 113 cancelled CFDIs were lost for deductibility — financial damage ~$890k MXN in VAT plus ~$1.2M MXN in ISR. Fix cost: $185k MXN (consulting + custom dev + 32 days of partial operation). Avoidance cost: installing the mandatory-attachment workflow from day one — ~$25k MXN. The lesson: the \"convenience\" of issuing CFDIs on trust costs 7–8 times more than running the right workflow from the start.

i
This kind of rescue is standard in our LATAM case portfolio. The methodology starts with an Odoo audit of 4-6 hours, not with replacing the ERP.

CFDI 2026 readiness checklist — download the template

We built a 47-point Excel checklist to evaluate Odoo readiness for the 2026 CFDI reform: modules, PAC configuration, audit-trail policies, cancellation workflows, CSD monitoring, and CSD rotation. It also includes an Aclaración template for restoring a suspended CSD, based on the case above.

Download the CFDI Real-Ops 2026 checklist → (email-gated)

Conclusion

The 2026 CFDI SAT reform is not a new format. It's the enforcement layer that turns the existing CFDI 4.0 from \"electronic paper\" into legally binding proof of materiality. For an SMB on Odoo, the technical requirements get covered by the standard l10n_mx stack plus a custom module of 40 to 80 hours for the mandatory-attachment workflow and CSD-status monitoring. Per-case fix costs run in the tens of thousands of pesos; the cost of inaction runs in the millions.

Main recommendation: don't wait for the SAT visit. As of May 2026 we're already inside the first-half audit season. SAT publishes EFOS lists each quarter, and every new listing is a counterparty collapse for whoever used those RFCs in deduction. If your company's CFDI workflow includes \"issued over WhatsApp\" or \"no contract\", that is a running timer. An Odoo audit on real-operations readiness takes 4-6 hours and costs orders of magnitude less than restoring a CSD.

Related reading:

Frequently asked questions

Since when does SAT actually enforce the \"real operations\" rule?

January 1, 2026, under the 2026 fiscal reform published in the DOF in late 2025. Art. 69-B CFF (presumption of non-existence) was already in use; the new piece for 2026 is escalation to criminal typification under Art. 113 Bis and 113 Ter CFF, together with reinforced verification powers including photo, video, and audio evidence collection inside the taxpayer's premises.

Can Odoo Community be used for CFDI 2026?

Yes. The base l10n_mx localization in the OCA bundle covers issuance, cancellation, and the payment complement. Carta Porte 3.1 lives in a separate OCA module (l10n_mx_edi_carta_porte). For the real-operations audit trail, plan on a custom module of 40 to 80 hours with mandatory-attachment validation on account.move.

What does a CSD suspension cost in business terms?

For the 18-person distributor in the case above: $890k MXN in VAT + $1.2M MXN in ISR + 32 days of partial operation + $185k MXN in consulting ≈ $2.3M MXN in total. For retailers with fast inventory turnover the numbers go higher: each day without CFDI is a day of lost sales.

Which PACs does Odoo l10n_mx support out of the box?

SW Sapien, Solución Factible, Diverza, Edicom Mexico, and Facturama. For any other PAC you need a custom integration — on average 60 to 120 development hours.

What about CFDIs issued before 2026 without materiality support?

If SAT hasn't opened an audit, no need to panic. The reform applies to CFDIs issued from January 1, 2026 onward. Older ones still fall under Art. 69-B (presumption) using the same pre-2026 procedure. It's still good hygiene to retroactively assemble support for every CFDI in the last 5 years (the prescription window) in case an audit lands.

Can a CFDI be cancelled past the 3-day window?

Through the standard Portal SAT flow, no. If the recipient already accepted the CFDI (explicitly or by timeout), cancellation requires recipient acceptance via a formal exchange. In practice most PACs block late cancellation; it becomes a legal procedure.

Is a CFDI 5.0 coming?

Not on SAT's public roadmap. The 2026 reform targets enforcement of the existing CFDI 4.0 format, not a new one. CFDI 5.0 has not been announced and does not appear in public consultations or drafts.

Does materiality have to be on physical paper or is digital enough?

Digital is fine: electronically signed contract, PDF purchase order, photo of the delivery, email from the customer with the request. What SAT requires is that the document be verifiable, dated, and reasonably hard to fabricate after the fact. An attachment inside Odoo, with system timestamp and traceability of who uploaded it and when, is defensible.