Errores
Todos los errores traen la misma forma: un objeto error
con code
y message. El code es estable
y es
contra el que conviene programar; el mensaje está en español y puede cambiar de redacción.
details.invoice: la factura queda guardada en estado
error
para que puedas leer el motivo contra un folio real y reintentar sobre ella.
Un rechazo no gasta timbre.
Un validation_failed
es distinto: no
llega al PAC, no crea borrador y no toma folio.
De la API
Nuestros, y los que se resuelven de tu lado.
- unauthorized
- 401
- Falta la llave, no viene con Bearer, o ya fue revocada.
- payment_required
- 402
- La cuenta tiene un pago pendiente.
- not_found
- 404
- Ese recurso no es de tu cuenta, o no existe. Contestamos igual a los dos. También un issuer_id, customer_id o product_id que no es de ese emisor.
- rate_limited
- 429
- Pasaste el límite de peticiones. Espera los segundos que dice Retry-After.
- invoice_limit_reached
- 429
- Con el plan Básico, tu cuenta ya timbró 100 facturas este mes. Retry-After llega al día 1 del mes siguiente.
- missing_parameter
- 422
- Falta un campo obligatorio. El mensaje dice cuál.
- invalid_parameter
- 422
- Un campo está presente pero no se puede usar: una cantidad que no es número, una fecha que no es fecha.
- validation_failed
- 422
- Un dato no pasó nuestras validaciones. details trae cada campo con sus motivos. No se crea borrador ni se toma folio.
- issuer_required
- 422
- Tu cuenta tiene más de un emisor y la llamada no dijo cuál. Manda issuer_id.
- issuer_not_ready
- 422
- Al emisor le falta su RFC, su régimen, su código postal o su CSD.
- folio_conflict
- 409
- Otra factura tomó ese folio mientras timbrábamos ésta. Reintenta.
- document_unavailable
- 404
- La factura no está timbrada, o su comprobante todavía no llega.
- renderer_unavailable
- 503
- El servicio que arma el PDF no respondió. El XML sí está.
Al timbrar
Del estado del timbrado, no del comprobante. Todos llegan con
422
y la factura en details.invoice.
- pac_unavailable
- El PAC no contestó a tiempo y pudo haber timbrado. Reintenta con la misma Idempotency-Key: primero le preguntamos al PAC si timbró.
- stamping_unconfirmed
- No pudimos confirmar si el PAC timbró una factura que quedó sin respuesta. Búscala en el SAT por su folio y, si no aparece, timbra con otra Idempotency-Key.
- stamping_failed
- No pudimos preparar o terminar el timbrado por un motivo nuestro. El mensaje lo dice. Reintenta.
Al cancelar
Todos llegan con 422. La factura se queda como estaba. Un rechazo del PAC al cancelar
puede llegar también con uno de sus códigos.
- invalid_state
- Sólo se cancela una factura timbrada.
- invalid_cancellation_reason
- El motivo no es del catálogo, o es 01 y falta substitute_uuid.
- unknown_issuer
- El emisor no tiene un CSD con el que firmar la cancelación.
- cancellation_refused
- El PAC o el SAT no aceptaron la cancelación. El mensaje trae su motivo.
Del sello y de retenciones
- no_certificate
- 422
- Subir el sello: no reconocimos ningún certificado en lo que mandaste.
- payload_too_large
- 413
- Subir el sello: el envío pasa de 12 MB.
- schema_invalid
- 422
- El comprobante no pasó el XSD del SAT. No llegó al PAC ni costó timbre. Corrige los datos y vuelve a mandarlo; la misma Idempotency-Key sirve.
- invalid_complement
- 422
- Retenciones: el complemento no existe o le faltan campos.
Del PAC
Sobre el sello, el certificado y la cuenta. Todos llegan con
422
y la factura en details.invoice. Un código del PAC que no traducimos llega como
pac_error
con su texto.
- invalid_seal
- El sello no coincide con la cadena original.
- csd_mismatch
- El sello no corresponde al emisor del comprobante.
- csd_revoked
- El certificado está revocado o caduco. Sube uno vigente.
- csd_not_yet_valid
- La fecha de emisión no cae dentro de la vigencia del CSD.
- not_a_csd
- El certificado es una e.firma, no un CSD.
- csd_not_from_sat
- El certificado no lo expidió el SAT. Es lo que contesta producción a un CSD de prueba.
- duplicate_cfdi
- Ese comprobante ya tiene timbre.
- date_out_of_range
- La fecha de emisión tiene más de 72 horas, o está en el futuro.
- issuer_not_registered
- El RFC del emisor no aparece en el padrón del SAT.
- no_stamps_left
- El RFC emisor no tiene timbres asignados.
- account_suspended
- La cuenta del PAC está suspendida. Se puede reintentar.
De la matriz del Anexo 20
Las validaciones del SAT sobre el contenido del comprobante. Traducimos muchas a un código estable; aquí están
las más frecuentes, y la lista no es completa. Un rechazo que no traducimos llega como
pac_error
con el texto del SAT, que suele traer entre paréntesis el dato exacto que
falló. Si tu código no reconoce uno, trátalo como pac_error.
- cfdi_use_not_allowed
- El SAT dice que el uso del CFDI no lo admite el régimen o el tipo de persona del receptor. Casi siempre lo atrapamos antes como validation_failed; llega éste sólo si el SAT no está de acuerdo con nuestra matriz.
- invalid_cfdi_use
- El uso del CFDI no está en c_UsoCFDI.
- recipient_not_registered
- Ese RFC no está en el padrón del SAT, o está cancelado.
- recipient_name_mismatch
- La razón social tiene que ir tal cual el SAT la tiene, sin el régimen de capital.
- recipient_postal_code_mismatch
- El código postal del receptor no es el que el SAT tiene para ese RFC.
- recipient_regime_mismatch
- El régimen del receptor no es el que el SAT tiene registrado.
- invalid_payment_form
- La forma de pago no está en c_FormaPago.
- payment_form_must_be_99
- Una factura PPD lleva la forma de pago 99, por definir.
- exchange_rate_missing
- Falta el tipo de cambio, obligatorio en cualquier moneda que no sea MXN.
- invalid_issue_postal_code
- El código postal del lugar de expedición no está en c_CodigoPostal.
- invalid_product_key
- La clave de producto o servicio no está en c_ClaveProdServ.
- invalid_unit_key
- La clave de unidad no está en c_ClaveUnidad.
- total_mismatch
- El total no cuadra con el subtotal, los descuentos y los impuestos.
- unclassified
- El SAT rechazó sin clasificar el motivo. Si el PAC dio un detalle, el mensaje lo trae entre paréntesis.
Qué se reintenta
folio_conflict, pac_unavailable, stamping_failed, account_suspended,
no_stamps_left
y renderer_unavailable
son de estado, no
del comprobante: reintentar tiene sentido. rate_limited
e invoice_limit_reached
también, después de esperar lo que dice Retry-After; el segundo deja de aplicar en cuanto la cuenta cambia a Pro. Los demás describen algo que hay que corregir antes de volver a
llamar.
Reintenta siempre con llave de idempotencia.