Passer au contenu principal

Introducción

Esta guía cubre todos los posibles códigos de respuesta, formatos de error y mejores prácticas para manejar errores al integrarse con la API de Lovi.

📊 Códigos de estado HTTP

Respuestas exitosas

200 OK - Solicitud exitosa

Notificación procesada:
{
  "success": true,
  "message": "Notification queued successfully",
  "notification_id": "uuid-notification-123",
  "scheduled_time": "2024-12-25T10:30:00Z"
}
Plantillas obtenidas:
{
  "templates": [
    {
      "id": "template_001",
      "name": "welcome_user",
      "status": "approved"
    }
  ],
  "total": 1
}
Plantilla creada:
{
  "success": true,
  "message": "Template created successfully",
  "template": {
    "id": "new_template_123",
    "name": "order_confirmation",
    "status": "pending"
  }
}

Respuestas de error del cliente (4xx)

400 Bad Request - Parámetros inválidos

Campo requerido faltante:
{
  "error": "validation_failed",
  "message": "Required field missing",
  "details": {
    "field": "contact.number",
    "reason": "This field is required"
  },
  "request_id": "req_123456789"
}
Formato de parámetro inválido:
{
  "error": "validation_failed",
  "message": "Invalid parameter format",
  "details": {
    "field": "datetime_sending",
    "provided": "25-12-2024",
    "expected_format": "ISO 8601 (YYYY-MM-DDTHH:MM:SS)",
    "example": "2024-12-25T10:30:00"
  },
  "request_id": "req_123456790"
}
Número de teléfono inválido:
{
  "error": "validation_failed",
  "message": "Invalid phone number format",
  "details": {
    "field": "contact.number",
    "provided": "+34-666-033-135",
    "expected_format": "Números solo, sin + ni espacios",
    "example": "34666033135"
  },
  "request_id": "req_123456791"
}
Hora programada en el pasado:
{
  "error": "validation_failed",
  "message": "Scheduled time must be in the future",
  "details": {
    "field": "datetime_sending",
    "provided": "2024-12-20T10:00:00",
    "current_time": "2024-12-20T15:30:00Z"
  },
  "request_id": "req_123456792"
}

401 Unauthorized - Autenticación fallida

Clave de acceso inválida:
{
  "error": "unauthorized",
  "message": "Invalid or expired access key",
  "details": {
    "reason": "La access_key proporcionada no es válida o ha sido revocada"
  },
  "request_id": "req_123456793"
}
Clave de acceso faltante:
{
  "error": "unauthorized",
  "message": "Missing access key",
  "details": {
    "reason": "Se requiere el parámetro access_key en la URL"
  },
  "request_id": "req_123456794"
}

403 Forbidden - Acceso denegado

Permisos insuficientes:
{
  "error": "forbidden",
  "message": "Insufficient permissions for this resource",
  "details": {
    "reason": "Your API key does not have permission to create templates"
  },
  "request_id": "req_123456795"
}
Acceso a empresa denegado:
{
  "error": "forbidden",
  "message": "Access denied to company resources",
  "details": {
    "reason": "API key is not associated with the requested company"
  },
  "request_id": "req_123456796"
}

404 Not Found - Recurso no encontrado

Plantilla no encontrada:
{
  "error": "template_not_found",
  "message": "Template 'welcome_user' not found or not approved",
  "details": {
    "template_name": "welcome_user",
    "language": "es_ES",
    "suggestion": "Check template name and approval status"
  },
  "request_id": "req_123456797"
}
Agente no encontrado:
{
  "error": "agent_not_found",
  "message": "Voice agent not found",
  "details": {
    "agent_id": "uuid-invalid-agent",
    "suggestion": "Verify agent_id exists and is active"
  },
  "request_id": "req_123456798"
}

422 Unprocessable Entity - Error de lógica de negocio

Plantilla no aprobada:
{
  "error": "template_not_approved",
  "message": "Template is not in approved status",
  "details": {
    "template_name": "pending_template",
    "current_status": "pending",
    "required_status": "approved"
  },
  "request_id": "req_123456799"
}
Discrepancia de variables:
{
  "error": "variable_mismatch",
  "message": "Template variables don't match provided data",
  "details": {
    "template_variables": ["name", "course"],
    "provided_variables": ["name", "email"],
    "missing": ["course"],
    "unexpected": ["email"]
  },
  "request_id": "req_123456800"
}

429 Too Many Requests - Límite de tasa excedido

Límite de tasa alcanzado:
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Try again in 60 seconds",
  "details": {
    "limit": 100,
    "window": "1 hour",
    "reset_time": "2024-12-20T16:30:00Z"
  },
  "retry_after": 60,
  "request_id": "req_123456801"
}
Cuota diaria excedida:
{
  "error": "quota_exceeded",
  "message": "Daily notification quota exceeded",
  "details": {
    "quota": 10000,
    "used": 10000,
    "reset_time": "2024-12-21T00:00:00Z"
  },
  "request_id": "req_123456802"
}

Respuestas de error del servidor (5xx)

500 Internal Server Error

Error general del servidor:
{
  "error": "internal_error",
  "message": "An unexpected error occurred",
  "details": {
    "reason": "Internal server error"
  },
  "request_id": "req_123456803"
}

502 Bad Gateway

Error del servicio upstream:
{
  "error": "service_unavailable",
  "message": "WhatsApp service temporarily unavailable",
  "details": {
    "service": "whatsapp_gateway",
    "estimated_recovery": "2024-12-20T16:00:00Z"
  },
  "request_id": "req_123456804"
}

503 Service Unavailable

Modo mantenimiento:
{
  "error": "service_unavailable",
  "message": "Service temporarily unavailable for maintenance",
  "details": {
    "maintenance_window": "2024-12-20T02:00:00Z to 2024-12-20T04:00:00Z"
  },
  "request_id": "req_123456805"
}

🔄 Estrategias de reintento

Lógica de reintento recomendada

Código de estadoAcciónEstrategia de reintento
400, 404, 422No reintentarCorregir la solicitud e intentar de nuevo
401, 403No reintentarActualizar autenticación
429Reintentar con retrocesoUsar encabezado retry_after
500, 502, 503🔄 Reintentar con retroceso exponencialMáximo 3 intentos

Ejemplo de implementación

async function makeAPIRequest(url, data, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      });

      const result = await response.json();

      if (response.ok) {
        return result;
      }

      // Handle different error types
      if (response.status === 429) {
        const retryAfter = result.retry_after || 60;
        await sleep(retryAfter * 1000);
        continue;
      }

      if ([500, 502, 503].includes(response.status)) {
        if (attempt < maxRetries) {
          await sleep(Math.pow(2, attempt) * 1000); // Exponential backoff
          continue;
        }
      }

      // Don't retry for 4xx errors (except 429)
      throw new APIError(result.error, result.message, response.status);

    } catch (error) {
      if (attempt === maxRetries) throw error;
      await sleep(Math.pow(2, attempt) * 1000);
    }
  }
}

📝 Mejores prácticas

Registro de errores

Siempre registra estos campos:
{
  "timestamp": "2024-12-20T15:30:00Z",
  "request_id": "req_123456789",
  "endpoint": "/notify",
  "method": "POST",
  "status_code": 400,
  "error_code": "validation_failed",
  "error_message": "Required field missing",
  "user_id": "user_123",
  "company_id": "company_456"
}

Lista de verificación para manejo de errores

Validación previa a la solicitud
  • Validar formato del número de teléfono
  • Verificar campos requeridos
  • Validar formato de fecha y hora
  • Verificar que la plantilla existe
Monitoreo de solicitudes
  • Registrar todas las solicitudes API
  • Incluir request_id en los registros
  • Monitorear tiempos de respuesta
  • Rastrear tasas de error
Recuperación de errores
  • Implementar lógica de reintento apropiada
  • Almacenar en caché tokens de autenticación
  • Manejar límites de tasa correctamente
  • Proporcionar mensajes de error significativos
Experiencia del usuario
  • Mostrar mensajes de error amigables
  • Proporcionar retroalimentación accionable
  • No exponer detalles internos de errores
  • Ofrecer alternativas cuando sea posible

Monitoreo y alertas

Métricas clave a monitorear:
  • Tasa de error por endpoint
  • Tiempo de respuesta promedio
  • Golpes de límite de tasa
  • Fallos de autenticación
  • Errores de plantilla no encontrada
Umbrales de alerta:
  • Tasa de error > 5%
  • Tiempo de respuesta > 2 segundos
  • Límite de tasa > 10/hora
  • Fallos de autenticación > 20/hora

🛠️ Herramientas de desarrollo

Pruebas de errores

Probar diferentes escenarios de error:
# Falta access_key
curl -X POST https://cloud.lovi.ai/functions/v1/notify \
  -H "Content-Type: application/json" \
  -d '{"contact":{"number":"34666033135"}}'

# Número de teléfono inválido
curl -X POST https://cloud.lovi.ai/functions/v1/notify?access_key=test \
  -H "Content-Type: application/json" \
  -d '{"contact":{"number":"+34-666-033-135"}}'

# Fecha pasada
curl -X POST https://cloud.lovi.ai/functions/v1/notify?access_key=test \
  -H "Content-Type: application/json" \
  -d '{"datetime_sending":"2020-01-01T10:00:00"}'

Analizador de respuestas de error

class LoviAPIError extends Error {
  constructor(response) {
    super(response.message);
    this.name = 'LoviAPIError';
    this.code = response.error;
    this.statusCode = response.status;
    this.requestId = response.request_id;
    this.details = response.details;
  }

  isRetryable() {
    return [429, 500, 502, 503].includes(this.statusCode);
  }

  getRetryAfter() {
    return this.details?.retry_after || 60;
  }
}

🚨 Problemas comunes y soluciones

Problemas de autenticación

Problema: Invalid or expired access key Solución:
  1. Verificar que access_key esté en los parámetros de URL
  2. Verificar que la clave no haya sido revocada
  3. Asegurarse de usar la clave correcta de la empresa

Problemas con plantillas

Problema: Template not found Soluciones:
  1. Verificar la ortografía del nombre de la plantilla
  2. Verificar que el idioma de la plantilla coincida
  3. Asegurarse de que la plantilla esté aprobada
  4. Usar GET /templates para listar plantillas disponibles

Limitación de tasa

Problema: Too many requests Soluciones:
  1. Implementar retroceso exponencial
  2. Respetar las cabeceras retry_after
  3. Agrupar solicitudes cuando sea posible
  4. Monitorear patrones de uso

Validación de datos

Problema: Validation failed Soluciones:
  1. Validar datos antes de enviar
  2. Usar formato correcto de número de teléfono
  3. Verificar formato de fecha y hora
  4. Verificar que los campos requeridos estén presentes
Recuerde siempre incluir el request_id al contactar soporte para una resolución más rápida de problemas.