# Limiti di frequenza

> Come Emailit limita gli invii per workspace, gli header ratelimit di ogni invio, com’è fatta una risposta 429, gli altri limiti degli endpoint e come ritentare con backoff.

Emailit limita quanto velocemente e quanto può inviare un workspace, non quante chiamate API fai. Questa pagina spiega i limiti di invio, gli header che li riportano, i pochi endpoint con limiti propri e come applicare il backoff quando ricevi un `429`.

## Limiti di invio

Ogni workspace ha due limiti di invio. I nuovi workspace partono con questi valori predefiniti in ogni piano:

| Limite | Predefinito | Finestra |
| --- | --- | --- |
| Al secondo | 2 email | Finestra mobile di un secondo |
| Al giorno | 5000 email | Giorno di calendario in UTC, si azzera alle 00:00 UTC |

Come si applicano i limiti:

- **Per workspace.** Tutte le chiavi API e l’[SMTP relay](/it/docs/smtp/) condividono gli stessi contatori. Inviare tramite SMTP consuma la stessa quota dell’API.
- **Conteggio per destinatario.** Ogni indirizzo univoco tra `to`, `cc` e `bcc` è un’email. Una richiesta con tre destinatari conta come tre.
- **Contano solo gli invii.** I limiti si applicano a [Invia un’email](/it/docs/api-reference/emails/send/) e [Inoltra un’email](/it/docs/api-reference/emails/forward/). La lettura dei dati e la gestione delle risorse non rientrano nei limiti.
- **Controllo prima, conteggio dopo.** Un invio viene accettato finché il workspace non ha ancora raggiunto il limite, e i suoi destinatari vengono aggiunti ai contatori in seguito. Una sola richiesta con molti destinatari può portarti oltre il limite, e le richieste successive ricevono `429` finché la finestra non si libera.

Puoi vedere i limiti attuali e l’utilizzo di oggi nel riquadro **Sending Limits** della pagina **Dashboard**.

## Header dei limiti di frequenza

Le risposte degli endpoint di invio e di inoltro includono questi header:

| Header | Descrizione |
| --- | --- |
| `ratelimit-limit` | Le email che il workspace può inviare al secondo. |
| `ratelimit-remaining` | Le email rimanenti nella finestra di un secondo in corso. |
| `ratelimit-reset` | I secondi mancanti all’azzeramento della finestra al secondo. |
| `ratelimit-daily-limit` | Le email che il workspace può inviare al giorno. |
| `ratelimit-daily-remaining` | Le email rimanenti per oggi. |
| `ratelimit-daily-reset` | I secondi mancanti all’azzeramento del limite giornaliero alle 00:00 UTC. |
| `retry-after` | I secondi da attendere prima di ritentare. Inviato solo con le risposte `429`. |

```http
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
ratelimit-limit: 2
ratelimit-remaining: 1
ratelimit-reset: 1
ratelimit-daily-limit: 5000
ratelimit-daily-remaining: 4812
ratelimit-daily-reset: 52113
```

## Quando raggiungi un limite

Un invio oltre il limite restituisce `429 Too Many Requests` con un header `retry-after`. Il corpo indica quale limite hai raggiunto:

**429 Al secondo**

```json
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Maximum 2 messages per second allowed.",
  "limit": 2,
  "current": 2,
  "retry_after": 1
}
```

**429 Giornaliero**

```json
{
  "error": "Daily limit exceeded",
  "message": "Daily sending limit of 5000 messages has been reached.",
  "limit": 5000,
  "current": 5000,
  "retry_after": 41760
}
```

| Campo | Descrizione |
| --- | --- |
| `error` | `Rate limit exceeded` per il limite al secondo, `Daily limit exceeded` per il limite giornaliero. |
| `limit` | Il limite raggiunto. |
| `current` | Quante email erano già state conteggiate nella finestra. |
| `retry_after` | I secondi da attendere. `1` per il limite al secondo, e i secondi mancanti alle 00:00 UTC per il limite giornaliero. |

Quando una richiesta viene rifiutata non viene inviato nulla e non vengono consumati crediti. Se il rifiuto riguarda il limite al secondo, ritenta dopo una breve attesa. Se riguarda il limite giornaliero, metti l’email in coda e inviala dopo l’azzeramento, oppure chiedi un limite più alto.

## Altri limiti

Alcuni endpoint hanno limiti propri:

| Endpoint | Limite | Conteggiato per |
| --- | --- | --- |
| `POST /emails/{id}/forward` | 3 all’ora | Workspace |
| `POST /webhooks/{id}/test` | 5 al minuto | Indirizzo IP |
| Link ospitati di iscrizione e disiscrizione (`/subscribe/{token}`, `/unsubscribe/{token}`) | 30 al minuto | Indirizzo IP |
| Endpoint pubblici dei moduli: caricamento di un modulo (`GET /forms/{token}`) | 60 al minuto | Indirizzo IP |
| Endpoint pubblici dei moduli: invio di una risposta (`POST /forms/{token}/submit`) | 30 al minuto | Indirizzo IP |

Gli inoltri rientrano anche nei limiti di invio indicati sopra. Oltre il limite di inoltri, l’API restituisce `429` con un header `retry-after`:

```json
{
  "error": "too_many_requests",
  "message": "Forwarding is limited to 3 emails per hour for this workspace. Try again later."
}
```

Questi limiti sono fissi e non cambiano con il piano o con i limiti di invio.

## Tutti gli altri endpoint

Gli endpoint che leggono dati o gestiscono risorse non hanno un limite fisso per endpoint. Mantieni un utilizzo ragionevole: usa un piccolo pool di richieste concorrenti invece di migliaia in parallelo, metti in cache i dati che cambiano di rado e usa i [webhook](/it/docs/webhooks/) invece del polling per lo stato delle email.

## Aumenta i limiti

- **Pro e Business.** I limiti aumentano automaticamente man mano che invii, in base alla [salute degli invii](/it/docs/deliverability/sending-health/). Emailit li aumenta al massimo una volta ogni sette giorni, e solo finché la salute degli invii è buona e nessuno dei tuoi domini è in pausa.
- **Tutti i piani.** Chiedi un aumento dalla pagina **Dashboard**: seleziona **Request Increase** nel riquadro **Sending Limits** e indica i limiti al secondo e giornalieri che ti servono, da dove proviene la tua lista e perché. Di solito il team di supporto esamina le richieste entro 24 ore.

Per tutti i limiti dei piani, vedi [Limiti e quote](/it/docs/limits/).

## Ritenta con backoff

Ritenta le risposte `429`, `409` (chiave di idempotenza ancora in elaborazione), `500` e `503`. Quando l’header `retry-after` è presente, attendi il numero di secondi indicato; quando manca, usa il backoff esponenziale con jitter. Invia un [`Idempotency-Key`](/it/docs/api-reference/idempotency/) perché un invio ritentato non venga mai consegnato due volte, e non aspettare la fine di un limite giornaliero in un ciclo di richieste.

**cURL**

```bash
# curl retries 429 and 5xx responses and honors retry-after.
curl https://api.emailit.com/v2/emails \
  --retry 5 --retry-max-time 60 \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042-confirmation" \
  -d '{
    "from": "Acme <orders@acme.com>",
    "to": "ada@example.com",
    "subject": "Your order #1042",
    "text": "Thanks for your order."
  }'
```

**Node.js**

```javascript
import { randomUUID } from 'node:crypto';

const RETRYABLE = new Set([409, 429, 500, 503]);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

export async function sendEmail(payload, maxAttempts = 5) {
  const idempotencyKey = randomUUID();

  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const response = await fetch('https://api.emailit.com/v2/emails', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.EMAILIT_API_KEY}`,
        'Content-Type': 'application/json',
        'Idempotency-Key': idempotencyKey,
      },
      body: JSON.stringify(payload),
    });
    const body = await response.json();
    if (response.ok) return body;

    const retryAfter = Number(response.headers.get('retry-after')) || 0;
    // Daily limit: retry_after is hours away, so give up and queue it.
    if (!RETRYABLE.has(response.status) || retryAfter > 60 || attempt === maxAttempts) {
      throw new Error(`Emailit ${response.status}: ${body.message ?? body.error}`);
    }

    const backoff = Math.min(1000 * 2 ** (attempt - 1), 30_000);
    await sleep(retryAfter ? retryAfter * 1000 : backoff + Math.random() * 250);
  }
}
```

**Python**

```python
import os
import random
import time
import uuid

import requests

RETRYABLE = {409, 429, 500, 503}

def send_email(payload, max_attempts=5):
    idempotency_key = str(uuid.uuid4())

    for attempt in range(1, max_attempts + 1):
        response = requests.post(
            "https://api.emailit.com/v2/emails",
            headers={
                "Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}",
                "Idempotency-Key": idempotency_key,
            },
            json=payload,
            timeout=30,
        )
        if response.ok:
            return response.json()

        retry_after = int(response.headers.get("retry-after", 0))
        # Daily limit: retry_after is hours away, so give up and queue it.
        if response.status_code not in RETRYABLE or retry_after > 60 or attempt == max_attempts:
            response.raise_for_status()

        backoff = min(2 ** (attempt - 1), 30) + random.random() / 4
        time.sleep(retry_after or backoff)
```

## Consigli per grandi volumi

- Invia da una coda con un numero fisso di worker, e dimensiona il pool in base al limite al secondo.
- Distribuisci nell’arco della giornata i grandi job in batch invece di avviarli tutti insieme, così un singolo job non consuma tutta la quota giornaliera.
- Tieni d’occhio `ratelimit-daily-remaining` e rallenta prima che arrivi a zero.
- Per le newsletter alle tue liste, usa le [campagne](/it/docs/campaigns/) invece di chiamare in ciclo l’endpoint di invio.

## Vedi anche

  - [Limiti e quote](/it/docs/limits/): Limiti di invio e quote dei piani in un unico posto.
  - [Salute degli invii](/it/docs/deliverability/sending-health/): Il punteggio che determina gli aumenti automatici dei limiti.
  - [Idempotenza](/it/docs/api-reference/idempotency/): Ritenta gli invii senza inviare due volte.
  - [Errori](/it/docs/api-reference/errors/): Tutti i formati di errore e i codici di stato.

---
Fonte: https://emailit.com/it/docs/api-reference/rate-limits/
