Manejar Errores
Cómo interpretar y manejar errores de la API de Sifende y rechazos de SIFEN en tu integración.
Esta guía explica cómo distinguir los distintos tipos de error que recibís de Sifende, qué hacer con cada uno y cuándo (no) reintentar.
Dos fuentes de error muy distintas
Mezclarlas en un mismo catch es una de las primeras causas de bugs en integraciones SIFEN.
| Fuente | Cuándo aparece | Cómo se ve |
|---|---|---|
| API Sifende | Inmediato, en el HTTP response | Status 400/401/403/404/422 + Problem Details JSON |
| SIFEN (rechazo asíncrono) | Después del polling, una vez que SIFEN procesa el lote | estado: "RECHAZADO" + mensajeRechazo con código SIFEN |
Errores de la API Sifende (síncronos)
Sigan el formato RFC 9457 Problem Details (excepto autenticación):
{
"type": "https://sifende.com.py/probs/validation-error",
"title": "Error de validación",
"status": 400,
"detail": "La solicitud contiene 2 error(es) de validación",
"errores": {
"receptor.numeroDocumento": "Número de documento es obligatorio",
"items[0].precioUnitario": "El precio no puede ser negativo"
}
}Cómo manejarlos en código
const res = await fetch('https://api.sifende.com.py/api/v1/documento-electronico', {
method: 'POST',
headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (!res.ok) {
const problem = await res.json();
if (problem.type?.includes('validation-error')) {
for (const [campo, mensaje] of Object.entries(problem.errores ?? {})) {
console.error(`Campo inválido: ${campo} → ${mensaje}`);
}
throw new ValidacionError(problem);
}
if (problem.type?.includes('invalid-enum-value')) {
console.error(`Valor inválido en ${problem.campo}. Aceptados:`, problem.valoresAceptados);
throw new EnumError(problem);
}
throw new ApiError(problem);
}
const cdc = await res.text();Tabla rápida de tipos
| Status | Tipo | Acción |
|---|---|---|
| 400 | validation-error | Revisar errores por campo, corregir y reenviar |
| 400 | invalid-enum-value | Usar uno de valoresAceptados |
| 400 | invalid-format | Corregir formato (fecha, RUC, CDC) |
| 401 | (texto plano) | API key inválida/expirada. Rotá la credencial desde el panel |
| 403 | access-denied | El usuario/key no tiene acceso a ese contribuyente |
| 404 | *-not-found | Recurso inexistente. Verificar IDs |
| 409 | duplicate-* | Ya existe. Usar el existente o cambiar identificador |
| 422 | documento-electronico-generation-error | Error de compliance SIFEN al generar el XML |
Catálogo completo en Errores.
Rechazos SIFEN (asíncronos)
Después de emitir, el documento queda en PENDIENTE o EN_LOTE. Una vez procesado, SIFEN devuelve un código con la respuesta. Los más frecuentes en producción:
| Código SIFEN | Significado | Cómo corregirlo |
|---|---|---|
| 1108 | Fecha fin de vigencia del timbrado incorrecta (timbrado vencido o mal configurado) | Renová o corregí la fechaFin del timbrado en SET y actualizalo en Sifende |
| 1302 | Falta tipoContribuyente del receptor para B2B | Completar tipoContribuyente: "CONTRIBUYENTE" |
| 1303 | Tipo de contribuyente receptor inválido (informado cuando es NO_CONTRIBUYENTE) | No incluyas tipoContribuyente en B2C no contribuyente |
| 1304 | Falta numeroDocumento (RUC) para receptor contribuyente | Completar el RUC del receptor |
| 1305 | RUC del receptor no requerido (informado para NO_CONTRIBUYENTE) | Eliminar numeroDocumento en B2C no contribuyente |
| 1306 | RUC del receptor inexistente en Marangatu (RUC no registrado en SET) | Confirmar el RUC con tu cliente |
| 1309 | DV del RUC del receptor incorrecto | Verificar digitoVerificador |
| 2026 | CDC asociado no existe o no está aprobado | Solo emitir NCE/NDE sobre FE en estado APROBADO |
Tabla completa: Rechazos SIFEN.
Cómo leer el rechazo
El campo mensajeRechazo del status response contiene el código y la descripción:
const resultado = await esperarResultadoSIFEN(cdc);
if (resultado.estado === 'RECHAZADO') {
// Ej: "1108 - Timbrado vencido"
const codigo = resultado.mensajeRechazo?.split(' ')[0];
log.warn({ cdc, codigo, motivo: resultado.mensajeRechazo }, 'DE rechazado por SIFEN');
}Cuándo reintentar (y cuándo no)
| Situación | ¿Reintentar? | Cómo |
|---|---|---|
| 5xx temporal de la API Sifende | ✅ | Backoff exponencial (1s, 2s, 4s…), máximo 3 intentos |
| 401 / 403 | ❌ | Arreglá credenciales, no reintentes con la misma |
400 validation-error | ❌ | Corregí los datos antes de reenviar |
404 documento-electronico-not-found | ❌ | El CDC no existe; no aparecerá reintentando |
| Rechazo SIFEN | ⚠️ | Emitir un DE nuevo con los datos corregidos. El original queda rechazado para siempre |
Nunca reintentes el mismo request rechazado por SIFEN. Cada DE consume un número del rango de timbrado: el rechazado ya gastó ese número y no se recupera. Para evitar gastar números, Inutilizar Numeración.
Recomendaciones de logging
En tu integración, logueá siempre:
cdc, para correlacionar con tu sistema.estadoymensajeRechazocuando consultes status.type,title,statusydetaildel Problem Details ante errores.- El request body completo en errores 4xx (excepto la API key); facilita reproducir el problema.
log.error({
cdc,
estado: resultado.estado,
mensajeRechazo: resultado.mensajeRechazo,
}, 'DE rechazado');Próximos pasos
- Para reintentar después de un rechazo, ver Reintentar Rechazados.
- Para ver el catálogo de códigos SIFEN, ver Rechazos SIFEN.
- Para problemas con certificados y firmado, ver Certificado Digital.