# Cancelar una factura > `POST https://api.cfdi.express/v1/invoices/{id}/cancel` — Cancela ante el SAT un CFDI timbrado, con motivo 01–04, y guarda el acuse de cancelación. URL de esta página: https://cfdi.express/docs/api/cancelar-factura Autenticación: requiere API key (`Authorization: Bearer sk_test_…` o `sk_live_…`) Idempotencia: requiere el header `Idempotency-Key`. Los motivos son los del catálogo del SAT: `01` comprobante emitido con errores _con_ relación (exige `folioSustitucion`, el UUID del CFDI que lo sustituye), `02` emitido con errores sin relación, `03` no se llevó a cabo la operación y `04` operación nominativa relacionada en una factura global. La cancelación consume un timbre. ### Parámetros de ruta | Campo | Tipo | Requerido | Descripción | |---|---|---|---| | `id` | string | sí | Id de la factura. | ### Headers | Campo | Tipo | Requerido | Descripción | |---|---|---|---| | `Idempotency-Key` | string | sí | Llave única de la operación de cancelación. | ### Cuerpo (JSON) | Campo | Tipo | Requerido | Descripción | |---|---|---|---| | `motivo` | string | sí | 01, 02, 03 o 04 del catálogo c_MotivoCancelacion. | | `folioSustitucion` | string | no | UUID del CFDI que sustituye al cancelado. Obligatorio con motivo 01. | ## Ejemplos ### cURL ```bash curl -X POST https://api.cfdi.express/v1/invoices/inv7k3q9x2m4v1t8p6d0n5cb/cancel \ -H "Authorization: Bearer sk_test_..." \ -H "Idempotency-Key: cancel_order_1001" \ -H "Content-Type: application/json" \ -d '{ "motivo": "02" }' ``` ### cURL — motivo 01 con sustitución ```bash curl -X POST https://api.cfdi.express/v1/invoices/inv7k3q9x2m4v1t8p6d0n5cb/cancel \ -H "Authorization: Bearer sk_test_..." \ -H "Idempotency-Key: cancel_order_1001_v2" \ -H "Content-Type: application/json" \ -d '{ "motivo": "01", "folioSustitucion": "7a2c8e10-55b4-4c31-9a12-1d0e6f3b8c44" }' ``` ## Respuesta ### 202 Accepted ```json { "id": "inv7k3q9x2m4v1t8p6d0n5cb", "object": "invoice", "status": "cancelled", "uuid": "9f1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d", "cancellation": { "motivo": "02", "folioSustitucion": null, "status": "cancelled", "chargedCentavos": 100, "acuseUrl": "https://files.cfdi.express/acuse-9f1b2c3d.xml?X-Amz-Expires=900&...", "requestedAt": "2026-08-18T18:02:44.310Z", "resolvedAt": "2026-08-18T18:02:46.882Z" } } ``` ## Errores | Status | code | Cuándo aparece | |---|---|---| | 400 | `validation_error` | Motivo inválido, falta folioSustitucion con motivo 01, o la factura no está timbrada. | | 401 | `unauthorized` | Falta el header Authorization o la llave es inválida. | | 402 | `insufficient_credits` | No hay saldo para el timbre de cancelación. | | 404 | `not_found` | La factura no existe en tu cuenta. | | 422 | `sat_rejected` | El SAT rechazó la cancelación. | | 503 | `pac_unavailable` | El PAC no está disponible. | ## Notas - Una factura PPD con complementos de pago vigentes no se puede cancelar: cancela primero los REPs con [POST /v1/payments/{id}/cancel](https://cfdi.express/docs/api/cancelar-complemento-de-pago). - El acuse XML del SAT queda disponible en `cancellation.acuseUrl` como URL firmada de 15 minutos. ## Relacionados - [GET /v1/invoices/{id}](https://cfdi.express/docs/api/obtener-factura) — Obtener factura - [POST /v1/payments/{id}/cancel](https://cfdi.express/docs/api/cancelar-complemento-de-pago) — Cancelar REP - [POST /v1/credit_notes](https://cfdi.express/docs/api/crear-nota-de-credito) — Timbrar nota de crédito --- Referencia completa: https://cfdi.express/docs/api · OpenAPI: https://api.cfdi.express/openapi.json · Llaves: https://dash.cfdi.express