# Cancelar un CFDI de retenciones > `POST https://api.cfdi.express/v1/retenciones/{id}/cancel` — Cancela ante el SAT una constancia de retenciones ya timbrada, con motivo 01–04. URL de esta página: https://cfdi.express/docs/api/cancelar-retencion Autenticación: requiere API key (`Authorization: Bearer sk_test_…` o `sk_live_…`) Header `x-account-id`: indica la cuenta. Si no eres miembro, la respuesta es 403. Idempotencia: requiere el header `Idempotency-Key`. Desde la v1.43.0. Los motivos son los del catálogo del SAT: `01` comprobante emitido con errores con relación (exige `folioSustitucion`, el UUID de la constancia que la 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. Consume un timbre. Responde 202 con el recurso: el estatus y el acuse quedan en él. En retenciones el SAT usa los mismos estatus que en un CFDI, con un 1 delante: `1201` cancelada y `1202` ya estaba cancelada. Exige `Idempotency-Key`. Si cancelas justo después de timbrar, el SAT puede responder `CR1205 - UUID No existe` durante cerca de un minuto. Ese intento se reembolsa; hay que reintentar después. Por MCP, `cancel_retencion` acepta el mismo cuerpo. Al completarse se puede avisar con el webhook `retencion.cancelled`. ### Parámetros de ruta | Campo | Tipo | Requerido | Descripción | |---|---|---|---| | `id` | string | sí | Id de la retención. | ### Headers | Campo | Tipo | Requerido | Descripción | |---|---|---|---| | `Idempotency-Key` | string | sí | Llave única de la operación de cancelación, de 1 a 255 caracteres. | ### Cuerpo (JSON) | Campo | Tipo | Requerido | Descripción | |---|---|---|---| | `motivo` | string | sí | 01, 02, 03 o 04. | | `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/retenciones/ret7k3q9x2m4v1t8p6d0n5cb/cancel \ -H "Authorization: Bearer sk_test_..." \ -H "Idempotency-Key: cancel-retencion-2026-09-prestador-42" \ -H "Content-Type: application/json" \ -d '{ "motivo": "02" }' ``` ## Respuesta ### 202 Accepted ```json { "id": "ret7k3q9x2m4v1t8p6d0n5cb", "object": "retencion", "status": "cancelled", "uuid": "9f1b2c3d-4e5f-4a6b-8c9d-0e1f2a3b4c5d", "cveRetenc": "26", "ejercicio": 2026, "mes": 9 } ``` ## Errores | Status | code | Cuándo aparece | |---|---|---| | 400 | `validation_error` | Motivo inválido o falta folioSustitucion con motivo 01. | | 401 | `unauthorized` | Falta el header Authorization o la llave es inválida. | | 402 | `insufficient_credits` | No hay saldo para el timbre de la cancelación. | | 404 | `not_found` | La retención no existe en tu cuenta. | | 422 | `sat_rejected` | El SAT rechazó la cancelación. | | 503 | `pac_unavailable` | El PAC no está disponible. | ## Notas - El 202 trae el recurso con su `status` y el acuse en `cancellation`. El OpenAPI publicado no detalla los campos internos de `cancellation`. ## Relacionados - [GET /v1/retenciones/{id}](https://cfdi.express/docs/api/obtener-retencion) — Consultar retención - [POST /v1/retenciones](https://cfdi.express/docs/api/timbrar-retencion) — Timbrar retención --- Referencia completa: https://cfdi.express/docs/api · OpenAPI: https://api.cfdi.express/openapi.json · Llaves: https://dash.cfdi.express