Errores
Guía completa de códigos de error y cómo manejarlos.
Errores
Cuando una solicitud falla, la API devuelve un objeto JSON con información sobre el error.
Formato de error
{
"error": "Descripción del error",
"code": "CODIGO_ERROR"
}
Códigos HTTP
| Código | Significado | Descripción |
|---|---|---|
| 200 | OK | Solicitud exitosa |
| 400 | Bad Request | Parámetros inválidos o faltantes |
| 401 | Unauthorized | API Key faltante o inválida |
| 403 | Forbidden | Sin permisos o límite excedido |
| 404 | Not Found | Recurso no encontrado |
| 429 | Too Many Requests | Rate limit excedido |
| 500 | Internal Server Error | Error del servidor |
| 503 | Service Unavailable | Servicio temporalmente no disponible |
Errores de autenticación (401)
| Código | Mensaje | Solución |
|---|---|---|
MISSING_API_KEY | API Key requerida | Incluye el header X-API-KEY |
INVALID_API_KEY | API Key inválida | Verifica que la key sea correcta |
EXPIRED_API_KEY | API Key expirada | Genera una nueva key |
DISABLED_API_KEY | API Key desactivada | Contacta soporte |
{
"error": "API Key inválida",
"code": "INVALID_API_KEY"
}
Errores de límites (403/429)
| Código | Mensaje | Solución |
|---|---|---|
DAILY_LIMIT_EXCEEDED | Límite diario excedido | Espera hasta mañana o actualiza tu plan |
RATE_LIMITED | Demasiadas solicitudes | Implementa backoff exponencial |
{
"error": "Has excedido el límite de solicitudes",
"code": "RATE_LIMITED",
"retryAfter": 60
}
El campo retryAfter indica los segundos que debes esperar antes de reintentar.
Errores de validación (400)
| Código | Mensaje | Causa |
|---|---|---|
INVALID_RUC | RUC inválido | RUC no tiene 11 dígitos |
SEARCH_TOO_SHORT | Búsqueda muy corta | Texto menor a 3 caracteres |
INVALID_DATE_FORMAT | Formato de fecha inválido | Usa YYYY-MM-DD |
MISSING_FIELD | Campo requerido faltante | Revisa el body de la solicitud |
{
"error": "El RUC debe tener 11 dígitos numéricos",
"code": "INVALID_RUC"
}
Errores de recursos (404)
| Código | Mensaje | Descripción |
|---|---|---|
NOT_FOUND | Contribuyente no encontrado | El RUC no existe en SUNAT |
EXCHANGE_RATE_NOT_FOUND | Tipo de cambio no disponible | No hay datos para esa fecha |
Errores del servidor (500/503)
| Código | Mensaje | Descripción |
|---|---|---|
INTERNAL_ERROR | Error interno del servidor | Error inesperado |
SUNAT_UNAVAILABLE | Servicio SUNAT no disponible | Los servicios de SUNAT están caídos |
DATABASE_ERROR | Error de base de datos | Problema de conexión |
Los errores 5xx son temporales. Implementa reintentos con backoff exponencial.
Manejo de errores
Ejemplo en TypeScript
interface ApiError {
error: string;
code: string;
retryAfter?: number;
}
async function consultarApi(endpoint: string) {
const response = await fetch(`https://api.kipudev.com${endpoint}`, {
headers: { "X-API-KEY": process.env.KIPUDEV_API_KEY },
});
if (!response.ok) {
const error: ApiError = await response.json();
switch (response.status) {
case 401:
throw new Error(`Autenticación fallida: ${error.error}`);
case 403:
throw new Error(`Sin permisos: ${error.error}`);
case 404:
return null; // Recurso no encontrado
case 429:
// Implementar retry después de error.retryAfter segundos
throw new Error(`Rate limited. Retry en ${error.retryAfter}s`);
default:
throw new Error(`Error ${response.status}: ${error.error}`);
}
}
return response.json();
}
Backoff exponencial
async function fetchWithRetry(
url: string,
options: RequestInit,
maxRetries = 3
) {
let lastError: Error;
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.status === 429) {
const data = await response.json();
const waitTime = data.retryAfter || Math.pow(2, i) * 1000;
await new Promise(r => setTimeout(r, waitTime));
continue;
}
return response;
} catch (error) {
lastError = error as Error;
const waitTime = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(r => setTimeout(r, waitTime));
}
}
throw lastError!;
}
Buenas prácticas
- ✅ Siempre maneja los errores de forma específica
- ✅ Implementa reintentos para errores temporales (5xx, 429)
- ✅ Usa backoff exponencial para reintentos
- ✅ Loggea los errores para debugging
- ✅ Muestra mensajes amigables al usuario final
- ❌ No reintentes errores 4xx (excepto 429)
- ❌ No expongas detalles técnicos al usuario final