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

# Errores y límites de frecuencia

> Códigos de estado HTTP, formato de las respuestas de error, límites de frecuencia y cómo tratar los errores en las API del seguimiento de conversiones.

## Códigos de estado HTTP

| Código                | Significado                                                                               | Acción                                                          |
| --------------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| `200`                 | Evento aceptado                                                                           | No hay nada que hacer                                           |
| `400`                 | Petición incorrecta: falta un campo, el formato no es válido o el `site_id` está inactivo | Corrige el contenido de la petición                             |
| `401`                 | Falta la cabecera `X-API-Key`                                                             | Añade la cabecera `X-API-Key`                                   |
| `403`                 | Clave no válida o revocada, o el `site_id` y la clave no coinciden                        | Revisa tu clave de API y el `site_id`                           |
| `413`                 | Contenido demasiado grande                                                                | Reduce su tamaño o divídelo en lotes más pequeños               |
| `422`                 | Error de validación: el detalle está en el cuerpo de la respuesta                         | Corrige el error del campo indicado                             |
| `429`                 | Límite de frecuencia superado                                                             | Espera y reintenta pasado el valor de la cabecera `Retry-After` |
| `500` / `502` / `503` | Error del servidor                                                                        | Reintenta con espera exponencial                                |

## Formato de la respuesta de error

Todas las respuestas de error devuelven un cuerpo JSON con los detalles:

```json theme={null}
{
  "detail": [
    {
      "loc": ["body", "scan_session_id"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

En los errores `400` con un solo mensaje:

```json theme={null}
{
  "detail": "site_id not found or inactive"
}
```

## Límites de frecuencia

| Endpoint                           | Límite                     | Ámbito           |
| ---------------------------------- | -------------------------- | ---------------- |
| `POST /ct` (eventos del navegador) | 100 peticiones por minuto  | Por dirección IP |
| `POST /collect/batch`              | 100 peticiones por minuto  | Por dirección IP |
| `POST /server-events`              | 1000 peticiones por minuto | Por clave de API |
| `POST /server-events/batch`        | 1000 peticiones por minuto | Por clave de API |

<Note>
  Los picos breves por encima del límite se toleran con un pequeño margen. Diseña tus clientes para que esperen tras un `429` en lugar de confiar en ese margen.
</Note>

## Patrón de tratamiento de errores

### Para eventos de servidor

```javascript theme={null}
async function sendEvent(payload) {
  const response = await fetch('https://track.scanova.io/server-events', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': process.env.SCANOVA_API_KEY,
    },
    body: JSON.stringify(payload),
  });

  if (response.ok) return await response.json();

  const error = await response.json().catch(() => null);

  if (response.status === 429) {
    const retryAfter = parseInt(response.headers.get('Retry-After') ?? '60', 10);
    throw new RetryableError(`Rate limited — retry after ${retryAfter}s`, retryAfter);
  }

  if (response.status >= 500) {
    throw new RetryableError(`Server error ${response.status}`);
  }

  // 400, 401, 403, 422 — do not retry, fix the request
  throw new PermanentError(`Request failed ${response.status}: ${JSON.stringify(error)}`);
}
```

### Lógica de reintento

Reintenta solo con errores pasajeros. Con los errores permanentes, detente de inmediato.

| ¿Reintentar?             | Códigos de estado                                          |
| ------------------------ | ---------------------------------------------------------- |
| Sí, con espera creciente | `429`, `500`, `502`, `503`, `504`, tiempo de espera de red |
| No, corrige la petición  | `400`, `401`, `403`, `413`, `422`                          |

Consulta [Idempotencia y reintentos](/es/conversion-tracking/server/idempotency-retries) para ver una implementación completa con espera exponencial.

## Causas habituales de `422`

| Error                                        | Solución                                                                      |
| -------------------------------------------- | ----------------------------------------------------------------------------- |
| El formato de `scan_session_id` no es válido | Debe ser un UUID válido (por ejemplo `7ad26d4f-3181-4ef8-b6ca-b8f59499dd43`)  |
| Falta `event_name`                           | Es obligatorio en los eventos de servidor                                     |
| `conversion_value.currency` no es válido     | Debe ser un código ISO 4217 de tres letras (por ejemplo `USD`, `EUR` o `GBP`) |
| `properties` es demasiado grande             | Mantenlo por debajo de 10 KB                                                  |
| Correo en texto plano en `properties`        | Usa `user_identifiers.email_hash` con un hash SHA-256                         |
