Retenciones
Timbra constancias de retenciones e información de pagos 2.0 enviando la constancia en JSON. La API arma el XML, lo sella con el CSD de tu cuenta y lo timbra.
/invoice/retention/invoice/cancelretentionLa petición
Igual que invoice/create: la constancia va en el parámetro json de un formulario. Tu cuenta necesita un CSD cargado y saldo de folios; cada constancia timbrada usa 1 folio.
curl -sS -X POST "$FD_API/invoice/retention" \
-H "X-Api-Key: $FD_API_KEY" \
--data-urlencode "json@retencion.json"{
"Version": "2.0",
"FolioInt": "R-1001",
"FechaExp": "AUTO",
"LugarExpRetenc": "64000",
"CveRetenc": "01",
"Emisor": {
"RfcE": "EKU9003173C9",
"NomDenRazSocE": "ESCUELA KEMPER URGATE",
"RegimenFiscalE": "601"
},
"Receptor": {
"NacionalidadR": "Nacional",
"Nacional": {
"RfcR": "XIA190128J61",
"NomDenRazSocR": "XENON INDUSTRIAL ARTICLES",
"DomicilioFiscalR": "76343"
}
},
"Periodo": { "MesIni": "10", "MesFin": "10", "Ejercicio": "2026" },
"Totales": {
"MontoTotOperacion": "10000.00",
"MontoTotGrav": "10000.00",
"MontoTotExent": "0.00",
"MontoTotRet": "1000.00",
"ImpRetenidos": [
{ "BaseRet": "10000.00", "ImpuestoRet": "001", "MontoRet": "1000.00", "TipoPagoRet": "04" }
]
}
}Estructura del JSON
Raíz
Version"2.0".FolioInt- Tu folio interno de la constancia.
FechaExpAAAA-MM-DDThh:mm:ss. Vacío oAUTOusa la hora actual de tu lugar de expedición.LugarExpRetenc- Código postal donde se expide.
CveRetenc- Clave de c_CveRetenc, por ejemplo
01servicios profesionales. Varias claves exigen su complemento:14Dividendos,16Intereses,18Pagos a extranjeros (Reten20107). DescRetenc- Obligatoria con la clave
25, otro tipo de retenciones (Reten20106). CfdiRetenRelacionadosTipoRelacionyUUIDde la constancia que sustituye.
Emisor, Receptor y Periodo
EmisorRfcE,NomDenRazSocEyRegimenFiscalE. A diferencia decreate, aquí se toman del JSON: tienen que ser los del CSD de tu cuenta.Receptor.NacionalidadRNacionaloExtranjero.Receptor.Nacional- Con receptor nacional:
RfcR,NomDenRazSocR,CurpR(opcional) yDomicilioFiscalR. Receptor.Extranjero- Con receptor extranjero:
NumRegIdTribR(opcional) yNomDenRazSocR. PeriodoMesIni,MesFinyEjercicio.
Totales
MontoTotOperacion, MontoTotGrav, MontoTotExent, MontoTotRet- Montos de la operación, gravado, exento y retenido.
UtilidadBimestral, ISRCorrespondiente- Para las claves que los piden.
ImpRetenidos- Una lista, aunque sea de un solo elemento:
BaseRet,ImpuestoRet,MontoRetyTipoPagoRet. Un objeto suelto en lugar de la lista se rechaza.TipoPagoRetva con su impuesto:03o04con ISR (001),01con IVA (002),02con IEPS (003) (Reten20135).
Los complementos de la constancia van en Complemento: Dividendos, EnajenaciondeAcciones, Intereses o Pagosaextranjeros. La colección de Postman trae un ejemplo de cada uno en la petición «Crear CFDI de Retenciones».
La respuesta
Ojo: este endpoint responde con llaves en español. El éxito trae mensaje y codigo en lugar de message y code; los errores traen las dos versiones.
{
"mensaje": "Timbrado exitoso",
"codigo": 200,
"cfdi": {
"NoCertificado": "30001000000500003416",
"Nacionalidad": "Nacional",
"NomDenRazSocR": "XENON INDUSTRIAL ARTICLES",
"DomicilioFiscalR": "76343",
"UUID": "0B7D4E21-5A6C-4F38-9E12-7C3A5B9D1F40",
"FechaTimbrado": "2026-11-03T11:02:10",
"RfcProvCertif": "AAA010101AAA",
"SelloCFD": "Q2V4...Zm9vYmFy",
"NoCertificadoSAT": "30001000000500003456",
"SelloSAT": "Tm9w...ZGF0YQ==",
"XmlBase64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4...",
"PDF": "https://app.facturadigital.com.mx/docs/pdf_retencion/0B7D4E21-5A6C-4F38-9E12-7C3A5B9D1F40",
"XML": "https://app.facturadigital.com.mx/docs/xml_retencion/0B7D4E21-5A6C-4F38-9E12-7C3A5B9D1F40"
}
}La constancia queda en tus retenciones emitidas, no en tus CFDI: no aparece en los listados de invoice/list* ni se puede enviar con invoice/send.
Errores
| code | Cuándo pasa | Qué hacer |
|---|---|---|
| 400 | No llegó el parámetro json, o no es un JSON válido. | Revisa el cuerpo del formulario. |
400 + json_type_validation | Un nodo tiene otro tipo: por ejemplo Emisor como texto o un elemento de ImpRetenidos como texto. No se envió nada ni se cobró. | errors[] dice qué campo; corrige el tipo. |
| 602 | Tu cuenta no tiene un CSD activo. | Carga tu CSD en Configuración. |
| 601 | Tu cuenta no tiene folios. | Compra folios. |
| 702 | El XML no cumple el esquema de Retenciones 2.0 (errorType: cfdi_retenciones_schema_validation). | errors[] trae campo y valor; corrígelos. |
| 400 + clave Reten20… | El SAT rechazó la constancia por una regla de su matriz. | Búscala en la matriz de errores (filtro Retenciones 2.0). |
| 5034 / 5037 | Igual que al timbrar un CFDI: 5037 no se envió nada; 5034 pudo haberse timbrado. | Ver Respuestas y errores. |
Cancelar una constancia
/invoice/cancelretentionMismos encabezados y motivos que la cancelación de un CFDI: UUID, MOTIVO (02 si no lo mandas) y FOLIOSUSTITUCION con el motivo 01. Usa el CSD de tu cuenta y no usa folio, aunque pide saldo mayor a cero.
curl -sS -X POST "$FD_API/invoice/cancelretention" \
-H "X-Api-Key: $FD_API_KEY" \
-H "UUID: 0B7D4E21-5A6C-4F38-9E12-7C3A5B9D1F40" \
-H "MOTIVO: 02"Revisado contra la API v5 en producción el 2026-11-03.