Saltar al contenido

API de cancelación de CFDI, cancela desde tu sistema

Envías el UUID y el motivo, y la API tramita la cancelación ante el SAT con tu CSD. La respuesta trae el resultado y el acuse del SAT en Base64. Cancelar no usa folio, y si timbras XML ya sellado, cancelas enviando tu CSD en la petición.

Lo que resuelve la API de cancelación

El trámite completo de cancelación de un CFDI 4.0, desde tu sistema.

Motivos 01 a 04

02 si no mandas motivo; 01 con el UUID que sustituye; 03 si la operación no se llevó a cabo; 04 para una operación nominativa relacionada en una factura global.

Acuse del SAT

Si la solicitud se acepta, recibes el acuse en Base64 y el CFDI queda como cancelado en tu cuenta, con su acuse guardado.

Con o sin CSD en tu cuenta

/invoice/cancel usa el CSD que tienes cargado. /invoice/cancelwithcsd recibe tu .cer, tu .key y la contraseña en la petición.

Cancelar no usa folio

Ninguna de las dos operaciones descuenta folios. /invoice/cancel sí pide que tu cuenta tenga saldo mayor a cero.

Estatus en el SAT

GET /validator/cfdi consulta en el SAT el estado del CFDI, si es cancelable y el estatus de su cancelación.

Retenciones

Las constancias de retenciones se cancelan con /invoice/cancelretention, con los mismos headers y los mismos motivos.

Cancelar una factura, de la petición a la respuesta

Cancelación con motivo 02. Los parámetros van en headers HTTP, no en el body; la llave va en X-Api-Key, como en el resto de la API.

Endpoints
POST /invoice/cancel
Headers UUID, MOTIVO (02 si no lo mandas) y, con motivo 01, FOLIOSUSTITUCION. Usa el CSD de tu cuenta.
POST /invoice/cancelwithcsd
Body form-encoded: uuid, motivo, folioSustitucion, b64Cer, b64Key y passwordCSD. No requiere CSD cargado.
GET /validator/cfdi
Con uuid, rfcemisor, rfcreceptor y total: estado, si es cancelable y estatus de cancelación en el SAT.
  • La respuesta es HTTP 200 aunque se rechace la solicitud: el resultado está en code.
  • code 200 es solicitud aceptada (uuid_estatus 201).
  • acuse es el XML del acuse del SAT, en Base64.
  • env_mode dice si la cancelación fue en Sandbox o en Productivo.
Producción
https://app.facturadigital.com.mx/api/v5
Sandbox
https://sandbox-app.facturadigital.com.mx/api/v5
cancelar.shDatos de muestra
# FD_API=https://sandbox-app.facturadigital.com.mx/api/v5
curl -X POST "$FD_API/invoice/cancel" \
  -H "X-Api-Key: $FD_API_KEY" \
  -H "UUID: 6FA90F39-2D7A-4F1C-9B3E-5C1D8A0E7B42" \
  -H "MOTIVO: 02"
respuesta-200.jsonDatos de muestra
{
  "message": "Solicitud de cancelación exitosa * Se considera una solicitud de cancelación exitosa, sin embargo esto no asegura su cancelación",
  "code": 200,
  "acuse": "PD94bWwgdmVyc2lvbj0iMS4wIj8+PEFjdXNlLi4u",
  "date": "2026-09-28 10:20:00",
  "uuid": "6FA90F39-2D7A-4F1C-9B3E-5C1D8A0E7B42",
  "uuid_estatus": 201,
  "env_mode": "Sandbox",
  "estatus_uuid": 201,
  "msg_error": null,
  "msg_error_detailt": null
}
cancelar-con-csd.shDatos de muestra
# Motivo 01 con tu CSD en la petición (el CFDI nuevo ya está timbrado)
curl -X POST "$FD_API/invoice/cancelwithcsd" \
  -H "X-Api-Key: $FD_API_KEY" \
  --data-urlencode "uuid=6FA90F39-2D7A-4F1C-9B3E-5C1D8A0E7B42" \
  --data-urlencode "motivo=01" \
  --data-urlencode "folioSustitucion=0B7C2E51-8A4D-4E0F-A1C3-7D9E6F2B5A10" \
  --data-urlencode "b64Cer@csd-cer.b64" \
  --data-urlencode "b64Key@csd-key.b64" \
  --data-urlencode "passwordCSD=$CSD_PASSWORD"

Intégrala en 4 pasos

Del motivo a la confirmación en el SAT.

  1. 01

    Elige el motivo

    02 si el CFDI tiene errores y no lo vas a sustituir. 01 si lo reemplazas: primero timbras el nuevo con CfdiRelacionadosTipoRelacion "04" y el UUID original en CfdiRelacionados.

  2. 02

    Envía la solicitud

    POST /invoice/cancel con los headers UUID y MOTIVO, más FOLIOSUSTITUCION si el motivo es 01. Si no tienes CSD en tu cuenta, usa /invoice/cancelwithcsd.

  3. 03

    Lee code, no solo el HTTP

    La respuesta es HTTP 200 aunque el SAT no acepte la solicitud. code 200 es solicitud aceptada; con cualquier otro, revisa message, msg_error y msg_error_detailt.

  4. 04

    Confirma en el SAT

    Una solicitud aceptada no asegura la cancelación. Consulta el estatus con GET /validator/cfdi y los parámetros uuid, rfcemisor, rfcreceptor y total.

Errores frecuentes y cómo resolverlos

Los errores de tu petición (llave, UUID, saldo, parámetros) responden con HTTP 400. El resultado de la cancelación llega con HTTP 200 y su code en el cuerpo.

code 202Folio fiscal previamente cancelado.El CFDI ya estaba cancelado ante el SAT; no hace falta repetir la solicitud.
code 203El folio fiscal no corresponde al emisor.El UUID no es de tu RFC: usa la llave de la cuenta que emitió el CFDI.
code 205Folio fiscal no aplicable a cancelación. Pasa con CFDI recién timbrados: el SAT puede tardar hasta 48 horas en mostrarlos como vigentes.Espera y vuelve a enviar la solicitud.
code 207 · 208 · 209El motivo no es válido, el folio de sustitución no es válido o se mandó sin que el motivo lo requiera.FOLIOSUSTITUCION solo va con motivo 01 y es el UUID del CFDI que sustituye.
601/invoice/cancel con tu cuenta sin folios disponibles.Cancelar no descuenta folios, pero este endpoint pide saldo mayor a cero. Compra folios o usa /invoice/cancelwithcsd.
400Falta el header UUID: «UUID to be cancelled (folio fiscal) not found in the headers.»Manda UUID, MOTIVO y FOLIOSUSTITUCION como headers, no en el body.
400En /invoice/cancelwithcsd: uuid con formato inválido, motivo fuera de 01 a 04, motivo 01 sin folioSustitucion o un .cer del que no se puede leer el RFC.El mensaje dice qué parámetro corregir.
501La llave X-Api-Key no es válida o es de otro ambiente; el mensaje termina con [Environment: …].Usa la llave del ambiente al que llamas: sandbox y producción tienen llaves distintas.

Sigue con

Carta Porte 3.1

Timbra CFDI de ingreso y traslado con el complemento Carta Porte y las reglas del SAT revisadas antes de timbrar.

Complemento de pago

Timbra el REP de tus facturas PPD con el mismo endpoint y la misma llave.

Sandbox

Prueba cancelaciones gratis con la misma API v5 que producción.

Webhooks

Que tu sistema se entere de lo que pasa en tu cuenta sin consultar la API.

SDKs oficiales

Librerías para llamar la API v5 desde tu lenguaje, con los mismos endpoints.

API v5

Autenticación, endpoints y las tres formas de timbrar: JSON, XML en Base64 o archivo XML.

Preguntas sobre la API de cancelación

¿Algo que no está aquí? Escríbenos o revisa la referencia completa.

¿Cancelar por API usa folios?

No. Ni /invoice/cancel ni /invoice/cancelwithcsd descuentan folios. /invoice/cancel sí pide que tu cuenta tenga saldo mayor a cero (si no, responde code 601); /invoice/cancelwithcsd no revisa el saldo.

¿Qué motivo de cancelación uso?

01: comprobante emitido con errores con relación; requiere el UUID que lo sustituye. 02: comprobante emitido con errores sin relación; es el que se usa si no mandas motivo. 03: no se llevó a cabo la operación. 04: operación nominativa relacionada en una factura global.

¿Cómo cancelo una factura para sustituirla?

Primero timbra la nueva con CfdiRelacionadosTipoRelacion "04" y el UUID de la original en CfdiRelacionados. Después cancela la original con MOTIVO 01 y el UUID de la nueva en FOLIOSUSTITUCION.

¿Por qué recibo HTTP 200 si la cancelación no procedió?

Porque la respuesta trae el resultado de la solicitud, sea cual sea. Lee code: 200 es solicitud aceptada; cualquier otro valor trae el motivo en message, msg_error y msg_error_detailt. Los errores de tu petición, como una llave inválida o un UUID faltante, sí responden HTTP 400.

Si recibo code 200, ¿el CFDI ya está cancelado?

Quiere decir que el SAT aceptó la solicitud (uuid_estatus 201), y eso no asegura la cancelación. Si la cancelación requiere la aceptación de tu cliente, queda en proceso hasta que responda. Consulta el estatus con GET /validator/cfdi: escancelable y estatuscancelacion te dicen en qué va.

¿Puedo cancelar sin cargar mi CSD en la cuenta?

Sí, con /invoice/cancelwithcsd. Mandas uuid, motivo, folioSustitucion, b64Cer, b64Key y passwordCSD en el body form-encoded, no en headers, porque el certificado es grande. El RFC del emisor se lee del .cer.

¿Puedo probar cancelaciones en el sandbox?

Sí. En el sandbox la cancelación es de prueba y la respuesta lo indica con env_mode Sandbox. Tu cuenta de sandbox es aparte, así que nada de lo que canceles ahí toca tus CFDI de producción.

Prueba tus cancelaciones en el sandbox

Es gratis y usa la misma API v5 que producción. Cancelar no usa folio.