Riferimento
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 condividono gli stessi contatori. Inviare tramite SMTP consuma la stessa quota dell’API.
- Conteggio per destinatario. Ogni indirizzo univoco tra
to,ccebccè un’email. Una richiesta con tre destinatari conta come tre. - Contano solo gli invii. I limiti si applicano a Invia un’email e Inoltra un’email. 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
429finché 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/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: 52113Quando 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:
{
"error": "Rate limit exceeded",
"message": "Too many requests. Maximum 2 messages per second allowed.",
"limit": 2,
"current": 2,
"retry_after": 1
}{
"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:
{
"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 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. 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.
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 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 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."
}'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);
}
}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-remaininge rallenta prima che arrivi a zero. - Per le newsletter alle tue liste, usa le campagne invece di chiamare in ciclo l’endpoint di invio.