> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lovi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Error handling

## 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:**

```json theme={null}
{
  "success": true,
  "message": "Notification queued successfully",
  "notification_id": "uuid-notification-123",
  "scheduled_time": "2024-12-25T10:30:00Z"
}
```

**Plantillas obtenidas:**

```json theme={null}
{
  "templates": [
    {
      "id": "template_001",
      "name": "welcome_user",
      "status": "approved"
    }
  ],
  "total": 1
}
```

**Plantilla creada:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "error": "internal_error",
  "message": "An unexpected error occurred",
  "details": {
    "reason": "Internal server error"
  },
  "request_id": "req_123456803"
}
```

#### 502 Bad Gateway

**Error del servicio upstream:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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 estado | Acción                                      | Estrategia de reintento                   |
| ---------------- | ------------------------------------------- | ----------------------------------------- |
| `400, 404, 422`  | ❌ **No reintentar**                         | Corregir la solicitud e intentar de nuevo |
| `401, 403`       | ❌ **No reintentar**                         | Actualizar autenticación                  |
| `429`            | ⏰ **Reintentar con retroceso**              | Usar encabezado `retry_after`             |
| `500, 502, 503`  | 🔄 **Reintentar con retroceso exponencial** | Máximo 3 intentos                         |

### Ejemplo de implementación

```javascript theme={null}
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:**

```javascript theme={null}
{
  "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:**

```bash theme={null}
# 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

```javascript theme={null}
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.
