Generate CFDI de Nómina XML (complemento Nómina 1.2)
Skill: Convert a payroll run into a CFDI 4.0 with the Nómina 1.2 complemento, stamped by a PAC
Region: Mexico (México)
Category: Payroll — Recibo de nómina (CFDI de Nómina)
Does: Takes payroll data for an employee/period and produces a CFDI de Nómina — a cfdi:Comprobante (Version 4.0, TipoDeComprobante="N") carrying the complemento Nómina 1.2 (nomina12:Nomina) with Percepciones, Deducciones and OtrosPagos (including subsidio al empleo) — then stamped (timbrado) by a PAC which returns the TimbreFiscalDigital with the UUID.
Standard: SAT CFDI 4.0 (Anexo 20) + complemento Nómina 1.2
Every salary payment in Mexico must be documented with a stamped CFDI de Nómina; the employee's CFDIs feed the SAT's prefilled annual ISR return. The
Emisoris the employer (withRegistroPatronalfrom IMSS), theReceptoris the worker (withCurp,NumSeguridadSocial,TipoContrato,TipoRegimen, etc.). AllTipoPercepcion,TipoDeduccionandTipoOtroPagocodes come from the current SAT nómina catálogos (c_TipoPercepcion, c_TipoDeduccion, ...). Validate against the Anexo 20 + Nómina 1.2 XSDs before stamping.
When this applies
- Any payment of salaries, wages, assimilated income, severance, bonuses (aguinaldo), PTU, etc., to a worker.
TipoNomina = O(Ordinaria — regular periodic payroll) orE(Extraordinaria — aguinaldo, finiquito, liquidación, PTU).- The CFDI must be issued at payment and stamped within the SAT window; corrections re-issue with substitution (relación
04).
Input data required
| Input | Node / attribute |
|---|---|
| Employer RFC, name, regime, ZIP, IMSS registro patronal | Emisor@Rfc/@Nombre/@RegimenFiscal, nomina12:Emisor@RegistroPatronal |
| Worker RFC, name, CURP, NSS | Receptor@Rfc/@Nombre, nomina12:Receptor@Curp, @NumSeguridadSocial |
| Employment data | @FechaInicioRelLaboral, @Antiguedad, @TipoContrato, @TipoRegimen, @NumEmpleado, @Departamento, @Puesto, @RiesgoPuesto, @PeriodicidadPago, @SalarioDiarioIntegrado |
| Period | nomina12:Nomina@TipoNomina, @FechaPago, @FechaInicialPago, @FechaFinalPago, @NumDiasPagados |
| Earnings | Percepciones/Percepcion (TipoPercepcion, Clave, Concepto, ImporteGravado, ImporteExento) |
| Deductions | Deducciones/Deduccion (TipoDeduccion, Clave, Concepto, Importe) — ISR (002), IMSS (001) |
| Other payments | OtrosPagos/OtroPago (TipoOtroPago 002 = subsidio para el empleo → SubsidioAlEmpleo@SubsidioCausado) |
Mexican specifics: TotalGravado/TotalExento totals must equal the sum of the per-line gravado/exento amounts; the CFDI SubTotal/Descuento/Total reconcile against percepciones, otros pagos and deducciones.
Document structure
cfdi:Comprobante (Version=4.0, TipoDeComprobante=N, Moneda=MXN, SubTotal, Descuento, Total)
├── cfdi:Emisor / cfdi:Receptor
├── cfdi:Conceptos/cfdi:Concepto (ClaveProdServ=84111505, ClaveUnidad=ACT, ObjetoImp=01)
└── cfdi:Complemento
└── nomina12:Nomina (Version=1.2, TipoNomina, FechaPago, NumDiasPagados, TotalPercepciones, TotalDeducciones, TotalOtrosPagos)
├── nomina12:Emisor (RegistroPatronal)
├── nomina12:Receptor (Curp, NumSeguridadSocial, TipoContrato, TipoRegimen, SalarioDiarioIntegrado, ...)
├── nomina12:Percepciones (TotalGravado, TotalExento; Percepcion[])
├── nomina12:Deducciones (TotalImpuestosRetenidos; Deduccion[])
└── nomina12:OtrosPagos/OtroPago/nomina12:SubsidioAlEmpleo
The PAC then appends tfd:TimbreFiscalDigital (UUID).
Calculation rules
Percepciones/@TotalGravado= ΣPercepcion@ImporteGravado;@TotalExento= Σ@ImporteExento.@TotalSueldosgroups ordinary salary percepciones.Deducciones/@TotalImpuestosRetenidos= Σ ISR deduction (TipoDeduccion=002);@TotalOtrasDeducciones= Σ non-tax deductions (IMSS, loans, etc.).Nomina/@TotalPercepciones= TotalGravado + TotalExento;@TotalDeduccionesand@TotalOtrosPagosmirror their sections.- Subsidio al empleo is reported under
OtrosPagos(TipoOtroPago=002) withSubsidioAlEmpleo@SubsidioCausado, not as a percepción. - CFDI
Total= TotalPercepciones + TotalOtrosPagos − TotalDeducciones (net pay);SubTotal= TotalPercepciones + TotalOtrosPagos;Descuento= TotalDeducciones. - ISR is computed on the gravado portion per the SAT tariff for the
PeriodicidadPago.
Worked example (TipoNomina O, abridged)
<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante
xmlns:cfdi="http://www.sat.gob.mx/cfd/4"
xmlns:nomina12="http://www.sat.gob.mx/nomina12"
Version="4.0" Serie="N" Folio="500" Fecha="2026-06-04T08:00:00"
Sello="(sello CSD)" NoCertificado="30001000000400002463" Certificado="(base64)"
SubTotal="10000.00" Descuento="1850.00" Total="8150.00"
Moneda="MXN" TipoDeComprobante="N" Exportacion="01" LugarExpedicion="64000">
<cfdi:Emisor Rfc="AAA010101AAA" Nombre="ACME SA DE CV" RegimenFiscal="601"/>
<cfdi:Receptor Rfc="MEXJ800101HJ1" Nombre="JUAN PEREZ LOPEZ"
DomicilioFiscalReceptor="64000" RegimenFiscalReceptor="605" UsoCFDI="CN01"/>
<cfdi:Conceptos>
<cfdi:Concepto ClaveProdServ="84111505" ClaveUnidad="ACT" Cantidad="1"
Descripcion="Pago de nomina" ValorUnitario="10000.00" Importe="10000.00"
Descuento="1850.00" ObjetoImp="01"/>
</cfdi:Conceptos>
<cfdi:Complemento>
<nomina12:Nomina Version="1.2" TipoNomina="O" FechaPago="2026-06-04"
FechaInicialPago="2026-05-16" FechaFinalPago="2026-05-31" NumDiasPagados="15"
TotalPercepciones="10000.00" TotalDeducciones="1850.00" TotalOtrosPagos="0.00">
<nomina12:Emisor RegistroPatronal="B5510768108"/>
<nomina12:Receptor Curp="PELJ800101HNLRPN09" NumSeguridadSocial="12345678901"
FechaInicioRelLaboral="2020-01-15" Antiguedad="P328W" TipoContrato="01"
TipoRegimen="02" NumEmpleado="0007" PeriodicidadPago="04"
SalarioBaseCotApor="640.00" SalarioDiarioIntegrado="666.66"
ClaveEntFed="NLE" RiesgoPuesto="1"/>
<nomina12:Percepciones TotalSueldos="10000.00" TotalGravado="10000.00" TotalExento="0.00">
<nomina12:Percepcion TipoPercepcion="001" Clave="P001" Concepto="Sueldos"
ImporteGravado="10000.00" ImporteExento="0.00"/>
</nomina12:Percepciones>
<nomina12:Deducciones TotalOtrasDeducciones="600.00" TotalImpuestosRetenidos="1250.00">
<nomina12:Deduccion TipoDeduccion="002" Clave="D002" Concepto="ISR" Importe="1250.00"/>
<nomina12:Deduccion TipoDeduccion="001" Clave="D001" Concepto="IMSS" Importe="600.00"/>
</nomina12:Deducciones>
</nomina12:Nomina>
</cfdi:Complemento>
</cfdi:Comprobante>
When subsidio al empleo applies, add nomina12:OtrosPagos/nomina12:OtroPago TipoOtroPago="002" with a child nomina12:SubsidioAlEmpleo SubsidioCausado="...".
Validation checklist
-
TipoDeComprobante="N", complementonomina12:Nomina Version="1.2", correctTipoNomina(O/E) - Worker
Curp(18 chars) andNumSeguridadSocialvalid; employerRegistroPatronalpresent -
TipoContrato,TipoRegimen,PeriodicidadPago,RiesgoPuestofrom current nómina catálogos -
Percepcion/Deduccion/OtroPagocodes valid; gravado/exento split correct - Subsidio al empleo reported under
OtrosPagos(002) withSubsidioAlEmpleo@SubsidioCausado - Section totals reconcile with the CFDI
SubTotal/Descuento/Total; net pay = percepciones + otros pagos − deducciones - Passes Anexo 20 + Nómina 1.2 XSD; PAC timbrado succeeds with
UUID
Last updated: 2026-06-04 — confirm the active CFDI/SAT schema version, catálogos, and PAC/portal requirements against the current SAT specifications before use.