Saltar al contenido
oden.tax docs
POST /v1/mx/retentions
GET /v1/mx/retentions
GET /v1/mx/retentions/:id
GET /v1/mx/retentions/:id/xml

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.

No hay PDF ni cancelación: sólo se emite, se lee y se descarga el XML.

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.