curl --request POST \
--url https://api.ipsofactura.com/cfdi/cancelar \
--header 'Content-Type: application/json' \
--header 'x-api: <api-key>' \
--data '
{
"folio_fiscal": "3f2b91c4-77d1-4a0e-9d0e-2c4f5b6a1e88",
"motivo": "02",
"rfc_emisor": "EKU9003173C9"
}
'{
"acuse": "...",
"estatus": "cancelado",
"estatus_cancelacion": "201",
"fecha_cancelacion": "2026-07-21T10:00:00",
"id": "9a4f07ff-..."
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}Cancelar CFDI
Cancela un CFDI timbrado. Motivos: 01 (con sustitución, requiere uuid_sustitucion), 02, 03, 04.
Identifica el comprobante con exactamente uno de id (el identificador interno que devolvió el timbrado) o folio_fiscal (el UUID del SAT). folio_fiscal es la vía para cancelar un CFDI que no timbramos nosotros —por ejemplo el de tu proveedor anterior—: rfc_emisor debe ser una empresa activa de tu cuenta y con CSD vigente, porque la cancelación se firma con ese certificado. El CFDI ajeno queda registrado con su folio fiscal, así que su acuse, su GET /cfdi/{id}/estatus y sus webhooks funcionan igual que los de un CFDI propio; no aparece en GET /cfdi ni tiene XML ni PDF, porque nunca vimos el documento.
curl --request POST \
--url https://api.ipsofactura.com/cfdi/cancelar \
--header 'Content-Type: application/json' \
--header 'x-api: <api-key>' \
--data '
{
"folio_fiscal": "3f2b91c4-77d1-4a0e-9d0e-2c4f5b6a1e88",
"motivo": "02",
"rfc_emisor": "EKU9003173C9"
}
'{
"acuse": "...",
"estatus": "cancelado",
"estatus_cancelacion": "201",
"fecha_cancelacion": "2026-07-21T10:00:00",
"id": "9a4f07ff-..."
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}{
"code": "VALIDATION_ERROR",
"id": "<string>",
"idempotencyKey": "<string>",
"message": "CFDI40147: El RFC del receptor no se encuentra en la lista de contribuyentes inscritos no cancelados del SAT",
"retryAfter": 123,
"sat_code": "CFDI40147"
}Authorizations
API key emitida por Ipsofactura, enviada en el header x-api.
Headers
Alternativa a idempotency_key en el cuerpo: reenviar la misma llave devuelve la respuesta del primer intento (Idempotency-Replayed: true) en lugar de timbrar otra vez, y la misma llave con un cuerpo distinto es 422 IDEMPOTENCY_KEY_REUSED. Máximo 100 caracteres ASCII imprimibles, sin espacios. Si además envías el campo en el cuerpo, los dos valores deben coincidir; si no, la respuesta es 400 VALIDATION_ERROR.
100"order-4711"
Body
101|02|03|041[A-Z&Ñ]{3,4}[0-9]{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])[A-Z0-9]{2}[0-9A]Folio fiscal (UUID del SAT) del CFDI a cancelar. Es la vía para cancelar un comprobante que no timbramos nosotros: rfc_emisor debe ser una empresa activa de tu cuenta y con CSD vigente, porque la cancelación se firma con ese certificado. Excluyente con id.
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$Identificador interno del CFDI en ipsofactura, el que devolvió el timbrado. Excluyente con folio_fiscal.
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$Clave estable de la operación. Reintentar la cancelación con la misma clave devuelve la respuesta del primer intento en lugar de volver a llamar al PAC. Máximo 100 caracteres.
100^[\x21-\x7E]+$RFC del receptor del comprobante. Opcional, y sólo se toma en cuenta al cancelar por folio_fiscal: es el único dato del CFDI ajeno que podemos registrar. En el sandbox es además lo que selecciona un escenario forzado (los mismos RFC reservados del timbrado, p. ej. el que deja la cancelación en proceso).
13CFDI que sustituye al cancelado (requerido con motivo 01). Admite el id interno de un CFDI tuyo o, cuando cancelas por folio_fiscal, el folio fiscal en crudo: el sustituto de un comprobante ajeno suele ser otro comprobante ajeno.
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$