Request
cancellation object:
Motivos de cancelación (SAT)
For
01, first stamp the corrected invoice, then cancel the original referencing it:
cancel.substitution_folio_* and cancel.motivo_* codes in ../errors.md.
The cancellation lifecycle
cancelledimmediately when the CFDI is cancelable sin aceptación — e.g. low-amount invoices, or a receptor ofXAXX010101000(público en general). The SAT accepts on submission.cancel_pendingwhen the CFDI is cancelable con aceptación. The receptor has 72 business hours to accept or reject in their SAT buzón; if they do nothing it auto-cancels at the deadline. The API pollsconsultarEstatusComprobanteon a job and finalizes the status.cancel_rejectedwhen the receptor rejects, or the SAT returns a definitive negative verdict (e.g. the UUID is referenced by another live CFDI →cancel.not_applicable/cancel.not_cancellable).
The receptor-acceptance flow (con aceptación)
- You submit the cancellation →
cancel_pending. - The receptor sees a solicitud de cancelación in their SAT portal and accepts or rejects it.
- The worker’s cancellation-poll job re-queries SAT status until it resolves, then updates the
invoice and emits a webhook:
invoice.cancelledorinvoice.cancel_rejected.
The acuse
Oncestatus is cancelled, cancellation.acuse_available becomes true. The acuse is the SAT’s
XML receipt of the cancellation — retain it as proof for your accounting.
Notes
- Only a stamped invoice can be cancelled; drafts have no UUID at the SAT.
- Cancellation is signed with the emitter’s CSD (handled server-side from the fiscal profile).
- Time-window rules apply: cancellations past the period’s declaration date, or past the
global-invoice deadline, are refused (
cancel.date_after_declaration,cancel.global_invoice_deadline). - The same lifecycle runs in test mode — a público-en-general receptor cancels sin aceptación
(resolves immediately), while a normal receptor stays
cancel_pendinguntil it accepts, rejects, or the 72h window lapses — so you can rehearse both paths before going live.