Skip to main content

Formato de error

Todos los errores de la API usan el mismo formato JSON:
{
  "error": "xml_invalido",
  "message": "El nodo cfdi:Emisor no contiene el atributo RegimenFiscal.",
  "status": 400,
  "detail": {
    "xpath": "/cfdi:Comprobante/cfdi:Emisor",
    "sat_code": "CFDI33158"
  }
}
CampoDescripción
errorCódigo de error en snake_case. Úsalo para lógica en tu código.
messageDescripción legible del error.
statusHTTP status code.
detailInformación adicional específica del error (no siempre presente).

Errores por categoría

Autenticación (401 / 403)

CódigoCausaSolución
unauthorizedAPI key inválida, revocada o mal formada.Verifica que el header sea Authorization: Bearer ipso_....
scope_insuficienteTu API key no tiene los permisos necesarios.Contacta a soporte para revisar los permisos de tu cuenta.
cuenta_suspendidaTu cuenta está suspendida.Contacta a soporte.

XML inválido (400)

CódigoCausaSolución
xml_invalidoEl XML no cumple el esquema CFDI 4.0 del SAT.Revisa el campo detail.xpath para identificar el nodo problemático.
xml_mal_formadoEl XML no está bien formado (tags sin cerrar, encoding incorrecto).Asegúrate de que el XML sea UTF-8 y los tags estén correctamente anidados.
version_no_soportadaEl XML usa una versión anterior a CFDI 4.0.Actualiza tu generador de XML a CFDI versión 4.0.

CSD (400)

CódigoCausaSolución
csd_vencidoEl CSD del emisor está expirado.Tramita un nuevo CSD ante el SAT y actualízalo en Ipsofactura.
csd_no_encontradoLa empresa no tiene un CSD registrado.Sube el CSD con POST /empresas/{id}/certificados.
rfc_no_coincideEl RFC en el XML no coincide con el RFC del CSD registrado.Verifica que el RFC del emisor sea el correcto.

Duplicados (409 / 422)

CódigoCausaSolución
cfdi_duplicadoYa existe un CFDI con la misma serie, folio y RFC.Usa un folio diferente o consulta el CFDI existente con GET /cfdi/{uuid}.

Saldo (402)

CódigoCausaSolución
saldo_insuficienteNo tienes timbres disponibles.Contacta a soporte para recargar timbres.

PAC (503)

CódigoCausaSolución
pac_no_disponibleTodos los PACs de la red están caídos.Espera y reintenta con backoff exponencial. Consulta el status page.

Reintentos

¿Cuándo reintentar?

Status¿Reintentar?Notas
400NoError en tu request. Corrígelo antes de reintentar.
401 / 403NoProblema de credenciales.
402NoProblema de saldo.
409 / 422NoError de lógica de negocio.
429Demasiadas requests. Espera unos segundos y reintenta.
500Error interno. Reintenta máximo 3 veces.
503PAC no disponible. Usa backoff exponencial.

Backoff exponencial recomendado

Python
import time
import random

def timbrar_con_reintento(client, xml, max_intentos=3):
    for intento in range(max_intentos):
        try:
            return client.cfdi.timbrar(xml=xml)
        except PacNoDisponibleError:
            if intento == max_intentos - 1:
                raise
            espera = (2 ** intento) + random.uniform(0, 1)
            time.sleep(espera)

Problemas frecuentes

”Mi CFDI fue timbrado pero no lo recibo en la respuesta”

Esto puede pasar si la conexión se interrumpió después de que el PAC timbró pero antes de que la respuesta llegara a tu sistema. Antes de reintentar el timbrado, consulta si el CFDI ya existe:
GET /cfdi?serie={serie}&folio={folio}&rfc_emisor={rfc}
Si el CFDI existe, no lo timbres de nuevo — solo descargaría el XML existente.

”Mi CSD vence pronto, ¿qué pasa si no lo renuevo?”

Los CFDIs timbrados con el CSD anterior siguen siendo válidos — el SAT no los invalida. Pero a partir de la fecha de vencimiento no podrás emitir nuevas facturas hasta subir el CSD renovado. Monitorea el campo vigente_hasta en GET /empresas?include_certificados=true para anticiparte al vencimiento.

”El SAT rechazó mi cancelación”

El motivo más común es que el receptor rechazó activamente la cancelación antes de las 72 horas. En ese caso recibirás cancelacion_rechazada. Opciones:
  • Negocia con el receptor para que acepte la cancelación desde su portal del SAT.
  • Si el CFDI tiene un error de importe, emite una nota de crédito por la diferencia.

Idempotencia

El timbrado de CFDIs es idempotente por serie + folio + RFC. Si envías el mismo XML dos veces, el segundo intento regresará cfdi_duplicado (422) en lugar de cobrar un timbre adicional. Esto te protege contra doble cobro en caso de timeouts o reintentos.
La deduplicación se basa en la combinación serie + folio + rfc_emisor del XML. Si cambias cualquiera de estos valores, se considerará un CFDI distinto.