> ## 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.

# Gestione degli errori

> Gestisci gli errori dell'API Enrow in modo efficace — formati di risposta, codici di stato, logica di retry e best practice

L'API Enrow segnala i problemi tramite codici di stato HTTP e un corpo JSON di errore. Questa guida illustra i formati delle risposte di errore, gli errori più comuni e come risolverli, e come costruire una logica di retry affidabile. Per l'elenco completo dei codici, consulta [Codici di stato](/it/status-codes).

## Che aspetto ha una risposta di errore?

La maggior parte degli errori dell'API Enrow restituisce un semplice oggetto JSON con un unico campo `message`:

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

L'unica eccezione è un errore di **credito insufficiente (402)** sugli endpoint **singoli** (find singolo email/phone, verify singolo), che restituisce un campo `reason` insieme a `success`:

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

Le risposte di errore non includono mai i campi `error`, `status` o `retry_after`. Leggi il codice di stato HTTP per ramificare la tua logica e leggi `message` (o `reason`) per la descrizione leggibile.

## Quali sono gli errori più comuni e come li risolvo?

Gli errori riportati di seguito coprono la stragrande maggioranza delle richieste fallite. Ciascuno è accompagnato dal corpo della risposta restituito dall'API e dalla relativa soluzione.

### Perché ricevo un 400 Bad Request?

Un `400` significa che il payload della richiesta è malformato o manca un parametro obbligatorio:

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

**Soluzione**: verifica di fornire tutti i parametri obbligatori per l'endpoint. Ad esempio, [Trova email](/it/api-reference/email-finder/find-single) richiede `fullname` più `company_domain` oppure `company_name`.

### Perché ricevo un 401 Unauthorized?

Un `401` significa che la chiave API è mancante o non valida:

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

**Soluzione**: verifica che la chiave API sia corretta e inviata nell'header `x-api-key` (non `Authorization`). Consulta [Autenticazione](/it/authentication) per sapere come passare la chiave a ogni richiesta.

### Perché ricevo un 402 Insufficient Credits?

Un `402` significa che l'account non dispone di credito sufficiente per eseguire la richiesta:

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

Sugli endpoint **bulk**, lo stesso `402` viene restituito con la struttura standard `{ "message": "..." }`.

**Soluzione**: controlla il saldo del credito nella [Dashboard](https://app.enrow.io) o tramite `GET /account/info`. Ricarica i crediti o passa a un piano superiore su [enrow.io/pricing](https://enrow.io/pricing). Consulta [Crediti e fatturazione](/it/credits-billing) per sapere come vengono consumati i crediti per ciascun endpoint.

### Perché ricevo un 429 Rate Limit Exceeded?

Un `429` significa che sono state inviate troppe richieste in un breve intervallo:

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

**Soluzione**: attendi e riprova con backoff esponenziale. Consulta [Limiti di frequenza](/it/rate-limits) per i limiti previsti per ciascun piano.

### Perché ricevo un 500 Internal Server Error?

Un `500` significa che qualcosa è andato storto sul lato di Enrow:

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

**Soluzione**: riprova la richiesta con backoff. Se il problema persiste, contatta [api@enrow.io](mailto:api@enrow.io).

## Come gestisco gli errori nel codice?

Controlla il codice di stato HTTP prima di analizzare il corpo della risposta di successo, quindi solleva un errore che riporti il codice di stato, in modo che la tua logica di retry possa ramificarsi su di esso. Il campo `message` contiene la descrizione per la maggior parte degli errori, mentre `reason` la contiene per le risposte `402` degli endpoint singoli.

<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>

## Come riprovo le richieste fallite?

Riprova solo gli errori che vale la pena riprovare — `429` e `5xx` — e applica un backoff esponenziale tra i tentativi. Gli errori client nell'intervallo `4xx` (eccetto `429`) segnalano un problema con la richiesta stessa, quindi riprovarli non serve.

```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));
    }
  }
}
```

## Best practice

* **Non riprovare gli errori 4xx** (eccetto il 429) — correggi invece la richiesta
* **Riprova gli errori 429** — applica un backoff con ritardi esponenziali prima di riprovare
* **Riprova gli errori 5xx** — con backoff esponenziale
* **Usa i webhook** invece del polling per evitare di raggiungere inutilmente i limiti di frequenza — consulta [Come funzionano i webhook](/it/how-webhooks-work)
* **Registra gli errori con il contesto** — includi l'endpoint, i parametri e il timestamp per il debugging

## FAQ

<AccordionGroup>
  <Accordion title="Come distinguo un 402 sugli endpoint singoli rispetto a quelli bulk?">
    Sugli endpoint singoli (find singolo email/phone, verify singolo), un `402` restituisce `{ "reason": "Insufficient credits", "success": false }`. Sugli endpoint bulk, lo stesso `402` restituisce la struttura standard `{ "message": "..." }`. Leggere sia `message` sia `reason` (come fanno gli esempi di codice) gestisce entrambi i casi.
  </Accordion>

  <Accordion title="Quali errori dovrei riprovare automaticamente?">
    Riprova gli errori `429` (limite di frequenza) e `5xx` (server) con backoff esponenziale. Non riprovare altri errori `4xx` come `400`, `401` o `402` — indicano un problema con la richiesta, la chiave API o il saldo del credito che il solo riprovare non risolve.
  </Accordion>

  <Accordion title="Esiste un header retry_after che mi indichi quanto attendere?">
    No. Le risposte di errore non includono mai i campi `retry_after`, `error` o `status`. Usa il tuo backoff esponenziale tra i tentativi. Consulta [Limiti di frequenza](/it/rate-limits) per i limiti applicabili al tuo piano.
  </Accordion>

  <Accordion title="Dove leggo il messaggio di errore nella risposta?">
    Per la maggior parte degli errori, la descrizione si trova nel campo `message`. Per un `402` di credito insufficiente su un endpoint singolo, si trova invece nel campo `reason`. Ramifica sempre la tua logica sul codice di stato HTTP anziché analizzare il testo del messaggio.
  </Accordion>
</AccordionGroup>

## Passaggi successivi

<CardGroup cols={2}>
  <Card title="Codici di stato" icon="list-check" href="/it/status-codes">
    L'elenco completo dei codici di stato HTTP e dei loro significati.
  </Card>

  <Card title="Limiti di frequenza" icon="gauge-high" href="/it/rate-limits">
    Comprendi i limiti di richieste per ciascun piano per evitare gli errori 429.
  </Card>

  <Card title="Autenticazione" icon="key" href="/it/authentication">
    Come passare la tua chiave API nell'header x-api-key.
  </Card>

  <Card title="Crediti e fatturazione" icon="coins" href="/it/credits-billing">
    Scopri come vengono consumati i crediti per ciascun endpoint.
  </Card>
</CardGroup>
