Manejo de Errores
Incluso las mejores integraciones pueden fallar. Esta guía te ayuda a identificar, entender y resolver errores en la API de Place Analyzer.
Códigos de Estado HTTP
La API usa códigos de estado HTTP estándar. Aquí están los más comunes:
| Código | Nombre | Descripción | ¿Reintentar? |
|---|---|---|---|
200 | OK | Solicitud exitosa | ❌ No |
201 | Created | Recurso creado exitosamente | ❌ No |
400 | Bad Request | Datos inválidos en la solicitud | ❌ No (corregir datos) |
401 | Unauthorized | API Key inválida o faltante | ❌ No (corregir API Key) |
404 | Not Found | Recurso no encontrado | ❌ No (verificar URLs) |
429 | Too Many Requests | Límite de rate excedido | ✅ Sí (con backoff) |
500 | Internal Server Error | Error interno del servidor | ✅ Sí (temporal) |
Estructura de Respuesta de Error
Todos los errores siguen una estructura JSON consistente:
{ "errorCode": "VALIDATION_ERROR", "message": "Descripción legible del error", "details": { "field": "property.propertyType", "provided": "INVALID", "expected": ["Terreno", "Casa", "Duplex", "Departamento", "Deposito", "Tinglado", "Oficina", "Local Comercial", "Propiedad rural", "Casa quinta", "Edificio"] }, "timestamp": "2025-01-15T10:30:00Z", "requestId": "req-123456" }
Campos importantes:
errorCode: Código específico del error (ver catálogo abajo)message: Descripción en español del errordetails: Información adicional para debuggingtimestamp: Cuándo ocurrió el errorrequestId: ID único para soporte técnico
Catálogo de Códigos de Error
🔐 Errores de Autenticación
INVALID_API_KEY
- Descripción: La API Key proporcionada no es válida
- Causa común: API Key mal escrita o expirada
- Solución: Verificar API Key en el dashboard
{ "errorCode": "INVALID_API_KEY", "message": "La API Key proporcionada no es válida", "details": { "providedKey": "xxx", "expectedFormat": "PA-XXXX-XXXX" } }
MISSING_API_KEY
- Descripción: No se proporcionó API Key
- Causa común: Header faltante
- Solución: Incluir
-H "X-API-KEY: tu_api_key"
API_KEY_EXPIRED
- Descripción: La API Key ha expirado
- Causa común: Key antigua
- Solución: Generar nueva key en dashboard
INSUFFICIENT_PERMISSIONS
- Descripción: La API Key no tiene permisos para esta operación
- Causa común: Key de sandbox usada en producción
- Solución: Verificar entorno (sandbox vs producción)
✅ Errores de Validación
VALIDATION_ERROR
- Descripción: Datos inválidos en la solicitud
- Causa común: Campos faltantes o formato incorrecto
- Solución: Revisar y corregir los datos enviados
{ "errorCode": "VALIDATION_ERROR", "message": "Errores de validación en la solicitud", "details": { "errors": [ { "field": "latitude", "message": "El valor debe estar entre -90 y 90", "provided": 91 }, { "field": "property.propertyType", "message": "Debe ser uno de: Terreno, Casa, Duplex, Departamento, Deposito, Tinglado, Oficina, Local Comercial, Propiedad rural, Casa quinta, Edificio", "provided": "INVALID" }, { "field": "property.m2Covered", "message": "El área cubierta (m2Covered) es requerida para Departamentos" } ] } }
Campos de validación comunes:
Coordenadas:
latitude: debe estar entre -90 y 90longitude: debe estar entre -180 y 180
Propiedad:
propertyType: debe ser uno de los valores permitidos (Terreno,Casa,Duplex,Departamento,Deposito,Tinglado,Oficina,Local Comercial,Propiedad rural,Casa quinta,Edificio)m2Land,m2Built,m2Covered,m2SemiCovered: cuando se envían, deben ser >= 0- La obligatoriedad de
m2Land,m2Built,m2Covered,m2SemiCovered,propertyAgeypropertyConditiondepende depropertyType(ver Avalúos individuales)
Mensajes de campos requeridos por tipo:
- Terreno:
"El área del terreno (m2Land) es requerida para Terrenos" - Departamento:
"El área cubierta (m2Covered) es requerida para Departamentos","El área semicubierta (m2SemiCovered) es requerida para Departamentos","La antigüedad (propertyAge) es requerida para Departamentos" - Demás tipos:
"El área del terreno (m2Land) es requerida","El área construida (m2Built) es requerida","La antigüedad (propertyAge) es requerida","El estado de conservación (propertyCondition) es requerido"
🔍 Errores de Recurso No Encontrado
REQUEST_NOT_FOUND
- Descripción: El requestCode no existe
- Causa común: requestCode mal escrito o nunca existió
- Solución: Verificar que el requestCode sea correcto
{ "errorCode": "REQUEST_NOT_FOUND", "message": "No se encontró la solicitud con el código proporcionado", "details": { "providedCode": "PA-2025-INVALID", "suggestion": "Verifica que el código sea correcto" } }
RESULT_NOT_AVAILABLE
- Descripción: El resultado no está disponible aún
- Causa común: Avalúo aún en proceso (PENDING_PROCESSING)
- Solución: Esperar y consultar nuevamente
{ "errorCode": "RESULT_NOT_AVAILABLE", "message": "El resultado no está disponible aún", "details": { "requestCode": "PA-2025-001234", "currentStatus": "PENDING_PROCESSING", "suggestion": "Espera a que el estado sea COMPLETED" } }
PROPERTY_NOT_FOUND
- Descripción: La propiedad no existe
- Causa común: propertyId inválido
- Solución: Verificar el propertyId
📊 Errores de Rate Limiting
RATE_LIMIT_EXCEEDED
- Descripción: Has excedido el límite de requests
- Causa común: Demasiadas consultas en poco tiempo
- Solución: Implementar backoff exponencial
{ "errorCode": "RATE_LIMIT_EXCEEDED", "message": "Has excedido el límite de requests por minuto", "details": { "currentLimit": 100, "requestsInWindow": 105, "resetTime": "2025-01-15T10:31:00Z", "retryAfter": 60 } }
🖥️ Errores del Servidor
INTERNAL_SERVER_ERROR
- Descripción: Error interno del servidor
- Causa común: Problemas temporales del servidor
- Solución: Reintentar con backoff exponencial
SERVICE_UNAVAILABLE
- Descripción: Servicio temporalmente no disponible
- Causa común: Mantenimiento o sobrecarga
- Solución: Reintentar más tarde
Estrategias de Manejo de Errores
1. Reintentos Inteligentes
class ApiClient { async request(url, options, maxRetries = 3) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const response = await fetch(url, options); if (response.ok) { return response.json(); } const error = await response.json(); // No reintentar errores de validación if (response.status === 400 || response.status === 401 || response.status === 404) { throw new Error(`${error.errorCode}: ${error.message}`); } // Reintentar errores del servidor if (attempt === maxRetries) { throw new Error(`Error después de ${maxRetries} intentos: ${error.message}`); } // Backoff exponencial const delay = Math.pow(2, attempt) * 1000; await new Promise(resolve => setTimeout(resolve, delay)); } catch (error) { if (attempt === maxRetries) { throw error; } } } } }
2. Manejo Específico por Error
async function handleValuationRequest(requestData, apiKey) { try { const response = await apiClient.post('/valuation-request', requestData, apiKey); return response; } catch (error) { switch (error.message.split(':')[0]) { case 'VALIDATION_ERROR': console.log('Datos inválidos:', error.details); // Mostrar formulario de corrección break; case 'INVALID_API_KEY': console.log('API Key inválida, redirigir a login'); // Redirigir a página de login break; case 'RATE_LIMIT_EXCEEDED': console.log('Rate limit excedido, mostrar mensaje de espera'); // Mostrar mensaje de espera break; default: console.log('Error inesperado:', error.message); // Error genérico } } }
3. Logging y Monitoreo
class ErrorLogger { static logError(error, context = {}) { const errorInfo = { timestamp: new Date().toISOString(), errorCode: error.errorCode, message: error.message, details: error.details, context: context, userAgent: navigator.userAgent, url: window.location.href }; // Enviar a servicio de logging console.error('API Error:', errorInfo); // En producción, enviar a servicio como Sentry // Sentry.captureException(error, { extra: errorInfo }); } }
Ejemplos Prácticos
Manejo de Rate Limiting
async function handleRateLimit() { const response = await fetch('/api/valuation-request', { headers: { 'X-API-KEY': API_KEY } }); if (response.status === 429) { const error = await response.json(); const resetTime = new Date(error.details.resetTime); const waitTime = resetTime.getTime() - Date.now(); console.log(`Rate limit excedido. Esperar ${Math.ceil(waitTime / 1000)} segundos`); await new Promise(resolve => setTimeout(resolve, waitTime)); return await makeRequest(); // Reintentar } }
Validación antes de enviar
function validateValuationRequest(data) { const errors = []; const property = data.property || {}; if (data.latitude == null || data.latitude < -90 || data.latitude > 90) { errors.push({ field: 'latitude', message: 'Debe estar entre -90 y 90' }); } if (data.longitude == null || data.longitude < -180 || data.longitude > 180) { errors.push({ field: 'longitude', message: 'Debe estar entre -180 y 180' }); } const validTypes = [ 'Terreno', 'Casa', 'Duplex', 'Departamento', 'Deposito', 'Tinglado', 'Oficina', 'Local Comercial', 'Propiedad rural', 'Casa quinta', 'Edificio' ]; if (!property.propertyType || !validTypes.includes(property.propertyType)) { errors.push({ field: 'property.propertyType', message: `Debe ser uno de: ${validTypes.join(', ')}` }); } // Campos condicionales según propertyType (ejemplos): // Terreno → m2Land // Departamento → m2Covered, m2SemiCovered, propertyAge // Demás tipos → m2Land, m2Built, propertyAge, propertyCondition return errors; }
Monitoreo y Alertas
Métricas importantes a monitorear:
- Tasa de errores por endpoint
- Tiempo de respuesta promedio
- Rate limits alcanzados
- Errores de autenticación
Dashboard de ejemplo:
// Enviar métricas a tu sistema de monitoreo function trackApiMetrics(endpoint, status, responseTime, errorCode = null) { analytics.track('api_request', { endpoint: endpoint, status: status, responseTime: responseTime, errorCode: errorCode, timestamp: new Date().toISOString() }); }
Soporte Técnico
Si no puedes resolver un error:
- Guarda el
requestIdde la respuesta de error - Incluye el
requestIden tu consulta de soporte - Proporciona el código que estás usando
- Describe qué esperabas que pasara
// Ejemplo de reporte de error completo const errorReport = { requestId: error.requestId, timestamp: error.timestamp, endpoint: '/valuation-request', method: 'POST', status: 400, errorCode: error.errorCode, userAgent: navigator.userAgent, requestData: requestData // ¡Sin API Key! };
Conclusión
El manejo proactivo de errores mejora la experiencia del usuario y reduce el soporte técnico. Implementa:
- ✅ Validación del lado del cliente antes de enviar
- ✅ Reintentos inteligentes para errores temporales
- ✅ Logging detallado para debugging
- ✅ Mensajes de error amigables para usuarios
- ✅ Monitoreo de métricas de error
¿Sigues teniendo problemas? Consulta nuestro glosario de estados y términos o contacta a soporte con tu requestId.