
CFDI relationship types: codes 01 to 07
May 17, 2026
A CFDI (Mexico's electronic invoice) went out with an error. You issued the new one, and when you tried to cancel the original, the SAT (Mexico's tax authority, Servicio de Administración Tributaria) told you it can't proceed because the replacement isn't related correctly. The new CFDI is valid: it's already stamped (stamping: the certification by a SAT-authorized provider that makes a CFDI valid). But you used the wrong relationship code, and now you have two live CFDIs for the same transaction. That's the cost of getting CFDI relationship types wrong. It happens more often than you'd think, because the PAC (Proveedor Autorizado de Certificación, a SAT-authorized provider that stamps CFDIs) doesn't warn you: it stamps the CFDI with the wrong code without a word.
The CfdiRelacionados node is one of those fields that look trivial until a replacement process breaks in production. The seven codes in the c_TipoRelacion catalog look interchangeable in the documentation. They aren't. This post explains which one to use in each case, and why code 04 is the one behind the most errors.
What are related CFDIs
A CFDI can point to an earlier CFDI through its UUID (folio fiscal, the unique ID the PAC assigns when it stamps a CFDI), using one of the seven codes in the c_TipoRelacion catalog. The earlier CFDI becomes its related CFDI (a CFDI this one replaces, credits, or pays, with its TipoRelacion key). That relationship tells the SAT that one CFDI corrects, replaces, records a return against, or complements another, instead of treating them as independent transactions with no connection between them.
Without that relationship, the SAT sees two separate invoices. With it, the SAT understands the story: the second one came from the first. That difference is what lets you cancel correctly, deduct a return, or close out an advance payment without duplicating income.
CFDI relationship types: the c_TipoRelacion catalog
The catalog has exactly seven codes. The descriptions are the SAT's, and they don't change. What matters, and what the official documentation doesn't explain well, is when each one applies in practice.
| Code | Description (SAT) | When to use it |
|---|---|---|
01 | Nota de crédito de los documentos relacionados (credit note for the related documents) | The new CFDI is a credit note (an Egreso CFDI, type E) that lowers the amount of an earlier invoice through a discount, a rebate, or a downward correction. |
02 | Nota de débito de los documentos relacionados (debit note for the related documents) | The new CFDI increases the amount of an earlier CFDI (interest, extra charges) without issuing a whole new invoice. |
03 | Devolución de mercancía sobre facturas o traslados previos (return of goods on previous invoices or transfers) | The customer returned goods, and you issue an Egreso CFDI that records that return against the original invoice. |
04 | Sustitución de los CFDI previos (replacement of previous CFDIs) | The new CFDI replaces one you cancel because of an error. It's the code of the cancel-and-reissue cycle. |
05 | Traslados de mercancías facturados previamente (transfers of goods invoiced previously) | You already invoiced the goods, and now you issue a transfer CFDI (type T, moves goods without a sale) to move them, related to those invoices. |
06 | Factura generada por los traslados previos (invoice generated from previous transfers) | The reverse of 05: the goods moved first with a transfer CFDI, and then you issue the invoice for those transfers. |
07 | CFDI por aplicación de anticipo (CFDI that applies an advance payment) | You close out an advance payment: the invoice for the full amount is related to the advance payment invoice (the CFDI you issue for money received before you deliver the goods or service) issued earlier. |
Most integrations use only three of these seven day to day: 01 for credit notes, 04 for replacements, and 07 for advance payments. Codes 05 and 06 usually come up together, in operations with transfer CFDIs, and 02 is rare because most people would rather issue a new invoice than a debit note.
A CFDI 4.0 detail that breaks integrations migrated from 3.3: you can now have several CfdiRelacionados nodes, each with its own TipoRelacion and its own UUIDs. In 3.3 there was a single node. If your code assumes a single relationship block, it breaks on the first case where a CFDI replaces one CFDI and applies an advance payment at the same time.
CFDI replacement: the 04 case almost everyone gets wrong
CFDI replacement (you issue a corrected CFDI related to the original with relationship type 04, then cancel the original with reason 01) causes the most problems because it's tied to the cancellation process. The sequence matters: first you issue the replacement CFDI, relating the original's UUID with TipoRelacion="04", and then you cancel the original with the replacement's UUID. Doing it the other way around is the classic mistake.
If you cancel the original CFDI first and then try to issue the replacement, you're left without the reference the cancellation reason (one of the SAT keys 01 to 04) needs. With reason 01 (Comprobante emitido con errores con relación, issued with errors, replaced by a related CFDI), the SAT asks for the UUID of the CFDI that replaces the canceled one, and that UUID doesn't exist yet if you didn't issue the replacement first. The full detail on cancellation reasons is in the CFDI cancellation guide, but the rule for this discussion is short: the replacement is born before the original dies.
The node in the replacement's XML looks like this:
<cfdi:CfdiRelacionados TipoRelacion="04">
<cfdi:CfdiRelacionado UUID="A1B2C3D4-1234-5678-9ABC-DEF012345678"/>
</cfdi:CfdiRelacionados>
Here's the trap nobody documents: the PAC checks that the UUID has a valid format and that the TipoRelacion code exists in the catalog, but it doesn't check whether the code is the logically correct one. If you put 01 where 04 should go, the CFDI gets stamped anyway. It ends up wrongly related, and nobody notices until the cancellation of the original fails, or until a SAT cross-check turns up the discrepancy. The error is silent at stamping time and loud weeks later.
How to relate a CFDI correctly
The order of operations is what separates a clean replacement from a pair of duplicate CFDIs you'll later have to explain to an auditor.
Identify the real relationship between the CFDIs#
Before you pick the code, pin down what's happening: a downward correction (01), a return of goods (03), a replacement because of an error (04), or closing out an advance payment (07). The code describes the real relationship, not the one that's easiest to set.
The CFDI that carries the relationship is issued before you cancel anything. In a replacement, the replacement CFDI is stamped first, with the original's UUID and TipoRelacion="04".
The UUID in CfdiRelacionado must be the exact UUID of the original CFDI, already stamped. A UUID with one character changed still gets stamped, and it breaks traceability without any warning.
Cancel the original with the right reason and UUID#
Only when it's a replacement. Reason 01 requires the UUID of the replacement you already issued. Without that UUID, the cancellation doesn't go through.
Confirm the status of both CFDIs#
The original must end up canceled, and the new one active (vigente: not canceled with the SAT) and related. Don't assume the result: check it. A live original plus an active replacement means duplicated income.
Common mistakes with related CFDIs
Canceling the original CFDI before issuing the replacement is the most expensive mistake in this whole chain. Cancellation reason 01 requires the UUID of the replacement CFDI, and if it doesn't exist because you didn't issue it first, you're left with a canceled CFDI with no replacement and a transaction with no valid CFDI. The order isn't negotiable: replacement first, cancellation second.
How to handle CFDI relationships programmatically
Relationship errors almost always come from orchestration, rarely from tax judgment. The team knows a replacement uses 04, but the system cancels and reissues in the wrong order, or builds the CfdiRelacionados node assuming a single block, or doesn't check the UUID before stamping. All of that is application logic that breaks in the cases nobody tested.
In Fiscalapi's API, the relationship is part of issuance: you send the related CFDIs in relatedInvoices, each with its relationshipTypeCode and uuid, and the API builds the CfdiRelacionados nodes from them. The API requires the same relationshipTypeCode for every related CFDI in a request, so each CFDI you issue through it has a single relationship type. Cancellation is a separate call with cancellationReasonCode, and with reason 01 the API requires the replacementUuid. The sequence lives in your system: stamp the replacement first, then cancel the original with the replacement's UUID. Keep that order and you never end up with a canceled CFDI and no replacement.
The Fiscalapi documentation describes both requests and the cancellation reasons, and the official SDKs for .NET, Node.js, Python, PHP, and Java cover the same calls. The examples on GitHub include credit notes with related CFDIs and cancellations with a replacement UUID. If the case is closing out a deferred payment, the payment complement (the complement that records each payment received against a PPD invoice; the type P CFDI that carries it is also called REP) has its own relationship logic, worth reviewing separately.
Frequently asked questions about CFDI relationship types
If your system still cancels first and reissues second, that's the order worth flipping before the next bulk correction. A badly orchestrated code 04 doesn't fail at stamping. It fails weeks later, when you already have hundreds of CFDIs to relate by hand and an auditor asking why there's duplicated income.