Retenciones
El CFDI de Retenciones e información de pagos 2.0: la constancia que emite quien paga y retiene impuestos. Una llamada
a POST /v1/mx/retentions
la arma, la sella y la timbra. Es síncrona: cuando te contestamos,
ya tiene UUID o ya sabemos por qué no.
Parámetros
Los importes van en pesos y pueden ir como texto o como número: el esquema de retenciones no tiene moneda. El emisor, su régimen y su código postal salen de su registro; no se mandan.
- issuer_id entero · requerido si tienes más de un emisor
- Con qué RFC se emite. Con un solo emisor lo puedes omitir.
- key string · requerido
- La clave de retención del catálogo c_CveRetenc del SAT (CveRetenc), de 01 a 28. Por ejemplo 18 para pagos a residentes en el extranjero.
- description string · opcional
- La descripción de la retención (DescRetenc).
- recipient objeto · requerido
- A quién se le retuvo. nationality es Nacional o Extranjero; si la omites, Nacional. Uno nacional lleva legal_name, tax_id (RFC) y postal_code, más curp si la tienes. Uno extranjero lleva legal_name y, si lo tiene, tax_registry_id, su número de registro tributario. legal_name siempre es obligatorio.
- period objeto · requerido
- from_month y to_month, del 1 al 12, y year. Los tres son enteros.
- withholdings arreglo · requerido
- Los impuestos retenidos, al menos uno. Cada uno lleva amount y payment_type, y opcionalmente tax y base.
- withholdings[].amount decimal · requerido
- Lo retenido, en pesos.
- withholdings[].payment_type string · requerido
- Clave de c_TipoPagoRet: 01 IVA definitivo, 02 IEPS definitivo, 03 ISR definitivo, 04 ISR provisional.
- withholdings[].tax string · opcional
- Clave de c_Impuesto: 001 ISR, 002 IVA, 003 IEPS. Si lo mandas, payment_type tiene que corresponderle: 001 con 03 o 04, 002 con 01, 003 con 02.
- withholdings[].base decimal · opcional
- La base de la retención, en pesos.
- taxable / exempt decimal · opcionales
- El monto gravado y el exento de la operación, en pesos. 0 si los omites. El total de la operación es la suma de los dos; no se manda.
- complement objeto · opcional
- Un complemento. format dice cuál, y hoy el único es pagosaextranjeros. Abajo están sus campos.
Complemento de pagos a extranjeros
El complemento Pagos a extranjeros 1.0, que va con la clave de retención 18. Es el único que soportamos. Con un receptor
extranjero, manda recipient.nationality: "Extranjero".
- format string · requerido
- pagosaextranjeros.
- effective_beneficiary booleano · opcional
- Si el beneficiario del pago es el beneficiario efectivo del cobro (EsBenefEfectDelCobro). true escribe SI; false u omitirlo escribe NO.
- payment objeto · requerido
- El residente en el extranjero (NoBeneficiario): country, la clave de país; concept, la clave de c_TipoContribuyenteSujetoRetencion; y description. Los tres son obligatorios.
- representative objeto · opcional
- El representante en México (Beneficiario): tax_id, curp, legal_name, concept y description. Si lo mandas, van los cinco.
Idempotencia
POST /v1/mx/retentions
acepta Idempotency-Key, como las facturas. La llave vale por emisor.
Si repites la llamada con la misma llave te devolvemos la primera constancia, sin comparar el cuerpo, con la cabecera Idempotency-Replayed: true.
Si la primera terminó en error y no tiene UUID, la llave se libera y el reintento emite una constancia nueva con otro folio. La que falló se queda en el listado. Si terminó en error pero sí tiene UUID, te devolvemos esa misma con su error.
Respuesta
201
con la constancia timbrada. Si el PAC la
rechaza contestamos
422
con su motivo como code, y la constancia en estado
error
dentro de details.retention, para que veas qué folio tomó.
- id
- entero
- El identificador dentro de oden.tax. Es lo que va en la URL.
- status
- string
- draft, stamping, stamped, error o canceled.
- uuid
- string o null
- El folio fiscal. Null mientras no haya timbre; la llave siempre está.
- number
- entero
- El folio interno (FolioInt). Lo asignamos nosotros, consecutivo por emisor.
- retention_key
- string
- La clave de retención que mandaste en key.
- description
- string o null
- La descripción, si la mandaste.
- period
- objeto
- from_month, to_month y year, como enteros.
- taxable / exempt
- string
- Gravado y exento, con dos decimales.
- operation_total
- string
- Gravado más exento (MontoTotOperacion).
- withheld
- string
- La suma de las retenciones (MontoTotRet).
- withholdings
- arreglo
- Las retenciones con tax, payment_type, base y amount. Los importes con dos decimales; tax y base sólo si los mandaste.
- complement
- objeto o null
- El complemento con los campos que aceptamos de lo que mandaste.
- issued_at / stamped_at
- string
- Fecha de emisión y de timbrado, en ISO 8601 con zona horaria. stamped_at es null sin timbre.
- issuer
- objeto
- id, tax_id, legal_name, tax_regime y postal_code (el lugar de expedición), tal como quedaron en la constancia.
- recipient
- objeto
- nationality, legal_name y los demás campos del receptor que traiga. No tiene id: el receptor no se guarda como cliente.
- xml_url
- string
- Sólo cuando ya tenemos el XML timbrado.
- error
- objeto
- Sólo en una constancia en estado error, con code y message.
Listar, consultar y descargar
GET /v1/mx/retentions
devuelve las de la cuenta, de la más reciente a la más antigua, con
la misma forma completa. Acepta page
(desde 1), per_page
(50 por omisión, 100 como máximo) e issuer_id
para ver sólo las de un emisor. La respuesta trae data, page,
per_page
y total.
GET /v1/mx/retentions/:id devuelve una, por nuestro id.
GET /v1/mx/retentions/:id/xml
devuelve el archivo timbrado como application/xml, descargable con el folio como nombre. Si la constancia no está timbrada,
o si está timbrada pero no tenemos su XML, contesta
404
con document_unavailable
y un mensaje que dice cuál de los dos casos es.
Errores
Todos con la forma de siempre, descrita en errores. Un rechazo del PAC trae el mismo código que en las facturas.
- unauthorized
- 401
- Falta la llave o ya fue revocada.
- payment_required
- 402
- La cuenta tiene un pago pendiente.
- issuer_required
- 422
- Tienes más de un emisor y la llamada no dijo cuál.
- not_found
- 404
- El issuer_id o la constancia no son de tu cuenta, o no existen.
- issuer_not_ready
- 422
- Al emisor le falta su RFC, su régimen, su código postal o su CSD. No se crea nada.
- missing_parameter
- 422
- Falta key, recipient, period, withholdings, el amount o el payment_type de una retención, o el format del complemento. El mensaje dice cuál. No se crea nada.
- invalid_parameter
- 422
- Un importe no es un número, o un campo de period falta o no es un entero. El mensaje dice cuál. No se crea nada.
- validation_failed
- 422
- Un receptor nacional sin tax_id o sin postal_code, un receptor sin legal_name, una nationality que no es Nacional ni Extranjero, o un mes fuera de 1 a 12. details trae el campo y el motivo. No se crea nada.
- schema_invalid
- 422
- El documento no pasó el esquema del SAT, o un payment_type no corresponde a su tax. Lo revisamos antes de mandarlo al PAC, así que no gasta timbre. La constancia queda en estado error con su folio, pero no viene en details: consúltala en el listado.
- invalid_complement
- 422
- El format no existe o al complemento le falta un campo. No gasta timbre. La constancia queda en estado error con su folio.
- folio_conflict
- 409
- Otra constancia del mismo emisor tomó ese folio al mismo tiempo. Vuelve a intentarlo.
- pac_unavailable
- 422
- No pudimos hablar con el PAC y no sabemos si timbró. La llave se queda con ese intento: repetir la llamada con la misma Idempotency-Key contesta esto mismo y no timbra otra. Revisa en el SAT si la constancia existe, y si no, emítela con una llave nueva.