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

# Gestión de errores

> Gestiona los errores de la API de Enrow de forma controlada: formatos de respuesta, códigos de estado, lógica de reintento y buenas prácticas

La API de Enrow señala los problemas mediante códigos de estado HTTP y un cuerpo de error en JSON. Esta guía explica los formatos de respuesta de error, los errores más habituales y cómo solucionarlos, además de cómo crear una lógica de reintento fiable. Para consultar la lista completa de códigos, consulta [Códigos de estado](/es/status-codes).

## ¿Qué aspecto tiene una respuesta de error?

La mayoría de los errores de la API de Enrow devuelven un objeto JSON sencillo con un único campo `message`:

```json theme={null}
{
  "message": "Human-readable error description"
}
```

La única excepción es un error de **crédito insuficiente (402)** en los endpoints **individuales** (búsqueda individual de email/teléfono, verificación individual), que devuelve un campo `reason` junto a `success`:

```json theme={null}
{
  "reason": "Insufficient credits",
  "success": false
}
```

Las respuestas de error nunca incluyen los campos `error`, `status` ni `retry_after`. Lee el código de estado HTTP para ramificar tu lógica y lee `message` (o `reason`) para obtener la descripción legible.

## ¿Cuáles son los errores más habituales y cómo los soluciono?

Los errores que se indican a continuación cubren la gran mayoría de las solicitudes fallidas. Cada uno incluye el cuerpo de respuesta que devuelve la API y la solución.

### ¿Por qué recibo un error 400 Bad Request?

Un `400` significa que el payload de la solicitud está mal formado o que falta un parámetro obligatorio:

```json theme={null}
{
  "message": "both company_domain and company_name are absent, input payload needs at least one of them"
}
```

**Solución**: Comprueba que estás proporcionando todos los parámetros obligatorios para el endpoint. Por ejemplo, [Buscar email](/es/api-reference/email-finder/find-single) requiere `fullname` más `company_domain` o `company_name`.

### ¿Por qué recibo un error 401 Unauthorized?

Un `401` significa que la clave de API falta o no es válida:

```json theme={null}
{
  "message": "This apikey is not valid"
}
```

**Solución**: Verifica que la clave de API es correcta y que se envía en la cabecera `x-api-key` (no en `Authorization`). Consulta [Autenticación](/es/authentication) para saber cómo pasar la clave en cada solicitud.

### ¿Por qué recibo un error 402 Insufficient Credits?

Un `402` significa que la cuenta no tiene créditos suficientes para ejecutar la solicitud:

```json theme={null}
{
  "reason": "Insufficient credits",
  "success": false
}
```

En los endpoints **masivos**, el mismo `402` se devuelve con el formato estándar `{ "message": "..." }` en su lugar.

**Solución**: Comprueba el saldo de créditos en el [Panel](https://app.enrow.io) o mediante `GET /account/info`. Recarga créditos o mejora el plan en [enrow.io/pricing](https://enrow.io/pricing). Consulta [Créditos y facturación](/es/credits-billing) para saber cómo se consumen los créditos en cada endpoint.

### ¿Por qué recibo un error 429 Rate Limit Exceeded?

Un `429` significa que se enviaron demasiadas solicitudes en un intervalo corto:

```json theme={null}
{
  "message": "Too Many Requests"
}
```

**Solución**: Espera y reintenta con retroceso exponencial. Consulta [Límites de frecuencia](/es/rate-limits) para conocer los límites de cada plan.

### ¿Por qué recibo un error 500 Internal Server Error?

Un `500` significa que algo falló del lado de Enrow:

```json theme={null}
{
  "message": "An unexpected error occurred"
}
```

**Solución**: Reintenta la solicitud con retroceso. Si el problema persiste, contacta con [api@enrow.io](mailto:api@enrow.io).

## ¿Cómo gestiono los errores en el código?

Comprueba el estado HTTP antes de analizar el cuerpo de éxito y, a continuación, lanza un error que incluya el código de estado para que tu lógica de reintento pueda ramificar en función de él. El campo `message` contiene la descripción para la mayoría de los errores, y `reason` la contiene para las respuestas `402` de los endpoints individuales.

<CodeGroup>
  ```javascript Node.js theme={null}
  async function findEmail(contact) {
    const response = await fetch('https://api.enrow.io/email/find/single', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': process.env.ENROW_API_KEY
      },
      body: JSON.stringify(contact)
    });

    if (!response.ok) {
      const body = await response.json();
      const error = new Error(`Enrow API error ${response.status}: ${body.message || body.reason}`);
      error.status = response.status;
      throw error;
    }

    return await response.json();
  }
  ```

  ```python Python theme={null}
  import requests
  import os

  def find_email(contact):
      response = requests.post(
          "https://api.enrow.io/email/find/single",
          json=contact,
          headers={
              "Content-Type": "application/json",
              "x-api-key": os.getenv("ENROW_API_KEY")
          }
      )

      if not response.ok:
          error = response.json()
          message = error.get("message") or error.get("reason")
          raise Exception(f"Enrow API error {response.status_code}: {message}")

      return response.json()
  ```
</CodeGroup>

## ¿Cómo reintento las solicitudes fallidas?

Reintenta solo los errores que merece la pena reintentar (`429` y `5xx`) y aplica un retroceso exponencial entre intentos. Los errores de cliente del rango `4xx` (excepto `429`) indican un problema con la propia solicitud, por lo que reintentarlos no servirá de nada.

```javascript theme={null}
async function requestWithRetry(fn, maxRetries = 3, baseDelay = 1000) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      const isLastAttempt = attempt === maxRetries - 1;

      // Don't retry client errors (except rate limits)
      if (error.status >= 400 && error.status < 500 && error.status !== 429) {
        throw error;
      }

      if (isLastAttempt) throw error;

      const delay = baseDelay * Math.pow(2, attempt);

      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
```

## Buenas prácticas

* **No reintentes los errores 4xx** (excepto 429): corrige la solicitud en su lugar
* **Reintenta los errores 429**: aplica retrocesos exponenciales antes de reintentar
* **Reintenta los errores 5xx**: con retroceso exponencial
* **Usa webhooks** en lugar de sondeo para evitar alcanzar los límites de frecuencia innecesariamente; consulta [Cómo funcionan los webhooks](/es/how-webhooks-work)
* **Registra los errores con contexto**: incluye el endpoint, los parámetros y la marca de tiempo para facilitar la depuración

## FAQ

<AccordionGroup>
  <Accordion title="¿Cómo distingo un 402 entre endpoints individuales y masivos?">
    En los endpoints individuales (búsqueda individual de email/teléfono, verificación individual), un `402` devuelve `{ "reason": "Insufficient credits", "success": false }`. En los endpoints masivos, el mismo `402` devuelve el formato estándar `{ "message": "..." }`. Leer tanto `message` como `reason` (como hacen los ejemplos de código) cubre cualquiera de los dos casos.
  </Accordion>

  <Accordion title="¿Qué errores debo reintentar automáticamente?">
    Reintenta los errores `429` (límite de frecuencia) y `5xx` (servidor) con retroceso exponencial. No reintentes otros errores `4xx` como `400`, `401` o `402`: indican un problema con la solicitud, la clave de API o el saldo de créditos que el reintento por sí solo no resolverá.
  </Accordion>

  <Accordion title="¿Existe una cabecera retry_after que indique cuánto debo esperar?">
    No. Las respuestas de error nunca incluyen los campos `retry_after`, `error` ni `status`. Usa tu propio retroceso exponencial entre reintentos. Consulta [Límites de frecuencia](/es/rate-limits) para conocer los límites que se aplican a tu plan.
  </Accordion>

  <Accordion title="¿Dónde leo el mensaje de error en la respuesta?">
    Para la mayoría de los errores, la descripción está en el campo `message`. Para un `402` de crédito insuficiente en un endpoint individual, está en el campo `reason` en su lugar. Ramifica siempre tu lógica según el código de estado HTTP en lugar de analizar el texto del mensaje.
  </Accordion>
</AccordionGroup>

## Próximos pasos

<CardGroup cols={2}>
  <Card title="Códigos de estado" icon="list-check" href="/es/status-codes">
    La lista completa de códigos de estado HTTP y sus significados.
  </Card>

  <Card title="Límites de frecuencia" icon="gauge-high" href="/es/rate-limits">
    Comprende los límites de solicitudes por plan para evitar errores 429.
  </Card>

  <Card title="Autenticación" icon="key" href="/es/authentication">
    Cómo pasar tu clave de API en la cabecera x-api-key.
  </Card>

  <Card title="Créditos y facturación" icon="coins" href="/es/credits-billing">
    Consulta cómo se consumen los créditos en cada endpoint.
  </Card>
</CardGroup>
