Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/eclipxe13/CfdiUtils/llms.txt

Use this file to discover all available pages before exploring further.

The standard validators run against every CFDI 3.3 document, whether you created it yourself with CfdiCreator33 or received it from a third party and are validating it with CfdiValidator33. The validators are automatically discovered and registered by MultiValidatorFactory from the CfdiUtils\\Validate\\Cfdi33\\Standard and CfdiUtils\\Validate\\Cfdi33\\RecepcionPagos namespaces — you do not need to register them manually. Each validator checks one specific area of the SAT specification and records one or more named results. Running all validators gives you a complete audit trail of every rule evaluated, not just the ones that failed.
Validation codes follow the pattern PREFIXNN, where the prefix identifies the validator (for example, MONDEC for monetary decimal rules) and the number distinguishes individual checks within that validator. Reference codes from the SAT specification (such as CFDI33106) are noted in parentheses where they apply.

Filtering Results by Code

Before diving into the full list of validators and codes, here is how to look up or filter assertions by a specific code in your application:
<?php
use CfdiUtils\CfdiValidator33;

$validator = new CfdiValidator33();
$asserts = $validator->validateXml(file_get_contents('/path/to/cfdi.xml'));

// Check a specific rule by code
if ($asserts->exists('MONDEC01')) {
    $assert = $asserts->get('MONDEC01');
    echo $assert->getStatus() . ': ' . $assert->getTitle() . PHP_EOL;
    if ($assert->getExplanation() !== '') {
        echo 'Detail: ' . $assert->getExplanation() . PHP_EOL;
    }
}

// Filter all errors and display their codes
foreach ($asserts->errors() as $error) {
    echo $error->getCode() . ' — ' . $error->getTitle() . PHP_EOL;
}

XML Schema Validator

XmlFollowSchema

This is the first validator to run. It verifies that the XML document conforms to every XSD schema declared in its xsi:schemaLocation attribute, including the SAT’s catalogue schemas. Because the SAT’s own XSD files encode many catalogue values (tax types, currency codes, etc.), this single check catches a large class of errors.
If XSD01 fails, the mustStop flag is set on the Asserts collection and all remaining validators are skipped. Fix schema errors before interpreting any other results.
CodeTitle
XSD01El contenido XML sigue los esquemas XSD

Comprobante Validators

Validates that monetary fields do not contain more decimal places than the currency allows. This rule applies only to MXN, USD, EUR, and XXX; for any other currency all statuses are NONE.The check also catches trailing zeros that push the decimal count above the permitted maximum.
CodeTitleSAT Rule
MONDEC01El subtotal del comprobante no contiene más de los decimales de la monedaCFDI33106
MONDEC02El descuento del comprobante no contiene más de los decimales de la monedaCFDI33111
MONDEC03El total del comprobante no contiene más de los decimales de la moneda
MONDEC04El total de impuestos trasladados no contiene más de los decimales de la monedaCFDI33182
MONDEC05El total de impuestos retenidos no contiene más de los decimales de la monedaCFDI33180
Validates the relationship between the payment complement (Complemento de Recepción de Pagos) and the FormaPago attribute. When a payment complement is present, the FormaPago attribute at the comprobante level must be absent.
CodeTitleSAT Rule
FORMAPAGO01El campo forma de pago no debe existir cuando existe el complemento para recepción de pagosCFDI33103
Validates consistency within the comprobante’s Impuestos node. When the node is present, at least one of the totals must exist; and when line-level taxes are present, the corresponding totals must appear at the comprobante level.
CodeTitle
COMPIMPUESTOSC01Si existe el nodo de impuestos entonces debe incluir el total de traslados y/o el total de retenciones
COMPIMPUESTOSC02Si existe al menos un traslado entonces debe existir el total de traslados
COMPIMPUESTOSC03Si existe al menos una retención entonces debe existir el total de retenciones
Validates the TipoCambio attribute relative to the Moneda value.
CodeTitleSAT Rule
TIPOCAMBIO01La moneda exista y no tenga un valor vacío
TIPOCAMBIO02Si la moneda es “MXN”, entonces el tipo de cambio debe tener el valor “1” o no debe existirCFDI33113
TIPOCAMBIO03Si la moneda es “XXX”, entonces el tipo de cambio no debe existirCFDI33115
TIPOCAMBIO04Si la moneda no es “MXN” ni “XXX”, el tipo de cambio debe seguir el patrón [0-9]{1,18}(.[0-9]{1,6})?CFDI33114, CFDI33117
Validates attribute presence and values depending on the TipoDeComprobante. Types T (traslado) and P (pago) have special restrictions — they may not carry payment method fields, tax nodes, discounts, or non-zero subtotals. Type N (nómina) must use MXN.
CodeTitleSAT Rule
TIPOCOMP01Si el tipo de comprobante es T, P o N, entonces no debe existir las condiciones de pago
TIPOCOMP02Si el tipo de comprobante es T, P o N, entonces no debe existir la definición de impuestosCFDI33179
TIPOCOMP03Si el tipo de comprobante es T o P, entonces no debe existir la forma de pago
TIPOCOMP04Si el tipo de comprobante es T o P, entonces no debe existir el método de pagoCFDI33123
TIPOCOMP05Si el tipo de comprobante es T o P, entonces no debe existir el descuento del comprobanteCFDI33110
TIPOCOMP06Si el tipo de comprobante es T o P, entonces no debe existir el descuento de los conceptosCFDI33179
TIPOCOMP07Si el tipo de comprobante es T o P, entonces el subtotal debe ser ceroCFDI33108
TIPOCOMP08Si el tipo de comprobante es T o P, entonces el total debe ser cero
TIPOCOMP09Si el tipo de comprobante es I, E o N, entonces el valor unitario de todos los conceptos debe ser mayor que cero
TIPOCOMP10Si el tipo de comprobante es N, entonces la moneda debe ser MXN
Validates that the optional comprobante-level discount, when present, is non-negative and does not exceed the subtotal.
CodeTitleSAT Rule
DESCUENTO01Si existe el atributo descuento, entonces debe ser menor o igual que el subtotal y mayor o igual que ceroCFDI33109
Validates that the Total attribute exists, is non-empty, and matches the numeric pattern [0-9]+(.[0-9]+)?.
CodeTitle
TOTAL01El atributo Total existe, no está vacío y cumple con el patrón [0-9]+(.[0-9]+)?

Concepto Validators

Validates the Descuento attribute on each cfdi:Concepto node.
CodeTitleSAT Rule
CONCEPDESC01Si existe el atributo descuento en el concepto, entonces debe ser menor o igual que el importe y mayor o igual que ceroCFDI33151
Validates the cfdi:Impuestos child node within each cfdi:Concepto. Rules cover the presence of the Base attribute, the handling of Exento factor types, and the requirements for Tasa or Cuota factors.
CodeTitleSAT Rule
CONCEPIMPC01El nodo de impuestos de un concepto debe incluir traslados y/o retencionesCFDI33152
CONCEPIMPC02Los traslados de los impuestos de un concepto deben tener una base y ser mayor a ceroCFDI33154
CONCEPIMPC03No se debe registrar la tasa o cuota ni el importe cuando el tipo de factor de traslado es exentoCFDI33157
CONCEPIMPC04Se debe registrar la tasa o cuota y el importe cuando el tipo de factor de traslado es tasa o cuotaCFDI33158
CONCEPIMPC05Las retenciones de los impuestos de un concepto deben tener una base y ser mayor a ceroCFDI33154
CONCEPIMPC06Las retenciones de los impuestos de un concepto deben tener un tipo de factor diferente de exentoCFDI33166

Emisor and Receptor Validators

Validates that the issuer’s RFC is structurally valid and is not one of the reserved generic values (XAXX010101000 or XEXX010101000), which are reserved for domestic and foreign general public recipients respectively and must never appear as the issuer.
CodeTitle
EMISORRFC01El RFC del emisor del comprobante debe ser válido y diferente de XAXX010101000 y XEXX010101000
Validates that the RegimenFiscal value is appropriate for the type of RFC used (persona física vs. persona moral). References SAT rules CFDI33130 and CFDI33131.
CodeTitle
REGFIS01El régimen fiscal contenga un valor apropiado según el tipo de RFC emisor
Validates that the recipient’s RFC is structurally valid. Unlike EmisorRfc, this validator does allow the generic public RFC (XAXX010101000) and the foreign RFC (XEXX010101000) because recipients may legitimately use them.
CodeTitle
RECRFC01El RFC del receptor del comprobante debe ser válido
Validates the ResidenciaFiscal attribute on the cfdi:Receptor node against the recipient’s RFC.
CodeTitleSAT Rule
RESFISC01Si el RFC no es XEXX010101000, entonces la residencia fiscal no debe existirCFDI33134
RESFISC02Si el RFC sí es XEXX010101000 y existe el complemento de comercio exterior, entonces la residencia fiscal debe establecerse y no puede ser “MEX”CFDI33135, CFDI33136
RESFISC03Si el RFC sí es XEXX010101000 y se registró el número de registro de identificación fiscal, entonces la residencia fiscal debe establecerse y no puede ser “MEX”CFDI33135, CFDI33136

Date Validator

FechaComprobante

Validates that the Fecha attribute on the comprobante is correctly formatted and falls within an acceptable date range. The document date must be after 2017-07-01 (when CFDI 3.3 took effect) and must not be set in the future beyond a configurable tolerance.
CodeTitle
FECHA01La fecha del comprobante cumple con el formato
FECHA02La fecha existe en el comprobante y es mayor que 2017-07-01 y menor que el futuro
The future tolerance defaults to 300 seconds (5 minutes) beyond the moment of validation. Both the absolute future cutoff and the tolerance can be configured on the FechaComprobante validator instance.

Digital Seal Validators

Validates the digital certificate embedded in the comprobante and verifies that the Sello attribute is consistent with it. This validator requires an XmlResolver to locate the certificate.
CodeTitle
SELLO01Se puede obtener el certificado del comprobante
SELLO02El número de certificado del comprobante igual al encontrado en el certificado
SELLO03El RFC del comprobante igual al encontrado en el certificado
SELLO04El nombre del emisor del comprobante igual al encontrado en el certificado
SELLO05La fecha del documento es mayor o igual a la fecha de inicio de vigencia del certificado
SELLO06La fecha del documento menor o igual a la fecha de fin de vigencia del certificado
SELLO07El sello del comprobante está en base 64
SELLO08El sello del comprobante coincide con el certificado y la cadena de origen generada
This is considered the most important validator because it proves the CFDI has not been altered after the SAT stamped it. It fetches the SAT certificate from https://rdc.sat.gob.mx/, builds the TimbreFiscalDigital cadena de origen, and verifies the SAT’s SelloSAT against it.
CodeTitle
TFDSELLO01El Sello SAT del Timbre Fiscal Digital corresponde al certificado SAT
The validator executes these steps in order:
1

Locate the TimbreFiscalDigital

If the complement does not exist, there is nothing to validate and the check is skipped.
2

Verify version 1.1

Only TimbreFiscalDigital version 1.1 is accepted. Any other version causes the check to be skipped.
3

Match SelloCFD with Sello

Confirms that SelloCFD in the TFD matches the Sello attribute of the comprobante. A mismatch means the CFDI has been tampered with.
4

Validate NoCertificadoSAT

Checks that the SAT certificate number is a valid numeric string.
5

Fetch the SAT certificate

Retrieves the certificate from https://rdc.sat.gob.mx/. If it cannot be fetched, the result is an error.
6

Build cadena de origen

Uses the configured XSLT builder to generate the TFD cadena de origen.
7

Verify the SAT seal

Verifies that the SAT’s SelloSAT matches the cadena de origen using the fetched certificate.
An issuer could potentially tamper with a CFDI by modifying the content while leaving the TimbreFiscalDigital and Sello attributes unchanged. In that case TimbreFiscalDigitalSello will not flag an error, but SelloDigitalCertificado will — because the comprobante Sello will no longer match the tampered cadena de origen.
Validates the version of the TimbreFiscalDigital complement when it is present.
CodeTitle
TFDVERSION01Si existe el complemento timbre fiscal digital, entonces su versión debe ser 1.1

Tax Sum Validator

SumasConceptosComprobanteImpuestos

This validator recalculates all monetary totals from the line items and compares them against the values declared at the comprobante level. It is one of the most comprehensive validators because it touches subtotals, discounts, transfer taxes, retained taxes, and the final total.
CodeTitle
SUMAS01La suma de los importes de conceptos es igual al subtotal del comprobante
SUMAS02La suma de los descuentos es igual al descuento del comprobante
SUMAS03El cálculo del total es igual al total del comprobante
SUMAS04El cálculo de impuestos trasladados es igual al total de impuestos trasladados
SUMAS05Todos los impuestos trasladados existen en el comprobante
SUMAS06Todos los valores de los impuestos trasladados coinciden con el comprobante
SUMAS07No existen más nodos de impuestos trasladados en el comprobante de los que se han calculado
SUMAS08El cálculo de impuestos retenidos es igual al total de impuestos retenidos
SUMAS09Todos los impuestos retenidos existen en el comprobante
SUMAS10Todos los valores de los impuestos retenidos coinciden con el comprobante
SUMAS11No existen más nodos de impuestos trasladados en el comprobante de los que se han calculado
SUMAS12El cálculo del descuento debe ser menor o igual al cálculo del subtotal

Recepción de Pagos Validators

These validators only activate when the TipoDeComprobante is P (pago). They validate the Complemento/Pagos structure according to the SAT’s Complemento para Recepción de Pagos specification (CRP).
CodeTitle
COMPPAG01El complemento de pagos debe existir si el tipo de comprobante es P y viceversa
COMPPAG02Si el complemento de pagos existe su versión debe ser 1.0
COMPPAG03Si el tipo de comprobante es P su versión debe ser 3.3
COMPPAG04No debe existir el nodo impuestos del complemento de pagos (CRP237)
Validates comprobante-level attributes that must comply with specific rules when the document is a payment receipt (TipoDeComprobante = P).
CodeTitle
PAGCOMP01Debe existir un solo nodo que represente el complemento de pagos
PAGCOMP02La forma de pago no debe existir (CRP104)
PAGCOMP03Las condiciones de pago no deben existir (CRP106)
PAGCOMP04El método de pago no deben existir (CRP105)
PAGCOMP05La moneda debe ser “XXX” (CRP103)
PAGCOMP06El tipo de cambio no debe existir (CRP108)
PAGCOMP07El descuento no debe existir (CRP107)
PAGCOMP08El subtotal del documento debe ser cero “0” (CRP102)
PAGCOMP09El total del documento debe ser cero “0” (CRP109)
PAGCOMP10No se debe registrar el apartado de Impuestos en el CFDI (CRP122)
Validates that the cfdi:Conceptos node contains exactly one cfdi:Concepto with the fixed attributes required by the SAT for payment receipt CFDIs.
CodeTitle
PAGCON01Se debe usar el concepto predefinido (CRP107 - CRP121)
CodeTitle
PAGUSO01El uso del CFDI debe ser “P01” (CRP110)
Each Pago node within the complement is validated against the following rules:
CodeTitleCRP Rule
PAGOS01Debe existir al menos un pago en el complemento de pagos
PAGO02En un pago, la fecha debe cumplir con el formato específico
PAGO03En un pago, la forma de pago debe existir y no puede ser “99”CRP201
PAGO04En un pago, la moneda debe existir y no puede ser “XXX”CRP202
PAGO05En un pago, cuando la moneda no es “MXN” no debe existir tipo de cambio, de lo contrario el tipo de cambio debe existirCRP203, CRP204
PAGO06En un pago, el tipo de cambio debe ser numérico, no debe exceder 6 decimales y debe ser mayor a “0.000001”
PAGO07En un pago, el monto debe ser mayor a ceroCRP207
PAGO08En un pago, el monto debe tener hasta la cantidad de decimales permitidos por la monedaCRP208
PAGO09En un pago, el monto del pago debe encontrarse entre los límites mínimo y máximo de la suma de los documentos
PAGO10En un pago, cuando el RFC del banco emisor de la cuenta ordenante existe
PAGO11En un pago, cuando el RFC del banco emisor sea “XEXX010101000”
PAGO12En un pago, cuando la forma de pago no sea bancarizada
PAGO13En un pago, cuando la forma de pago no sea bancarizada (cuenta ordenante)
PAGO14En un pago, cuando la cuenta ordenante existe debe cumplir con el patrón
PAGO15En un pago, cuando el RFC del banco emisor de la cuenta beneficiaria existe
PAGO16En un pago, cuando la forma de pago no sea 02, 03, 04, 05, 28, 29 o 99 (banco beneficiario)
PAGO17En un pago, cuando la forma de pago no sea 02, 03, 04, 05, 28, 29 o 99 (cuenta beneficiaria)
PAGO18En un pago, cuando la cuenta beneficiaria existe
PAGO19En un pago, cuando la forma de pago no sea 03 o 99 (tipo de cadena de pago)
PAGO20En un pago, si existe el tipo de cadena de pago debe existir el certificado de pago y viceversaCRP227, CRP228
PAGO21En un pago, si existe el tipo de cadena de pago debe existir la cadena de pago y viceversaCRP229, CRP230
PAGO22En un pago, si existe el tipo de cadena de pago debe existir el sello de pago y viceversaCRP231, CRP232
PAGO30En un pago, la suma de los valores registrados o predeterminados en el importe pagado de los documentos relacionados debe ser menor o igual que el monto del pagoCRP206

See Also

Validation Overview

Architecture, statuses, and how to validate both created and received CFDIs.

CFDI 4.0 Validation Rules

CFDI 4.0-specific validators and differences from the 3.3 validator set.

Build docs developers (and LLMs) love