Reference
Limity rychlosti
Jak Emailit omezuje odesílání pro každý workspace, hlavičky ratelimit u každého odeslání, jak vypadá odpověď 429, další limity endpointů a jak opakovat požadavky s rostoucím odstupem.
Emailit omezuje, jak rychle a kolik může workspace odesílat, ne kolik voláte API. Tato stránka vysvětluje limity odesílání, hlavičky, které je hlásí, několik endpointů s vlastními limity a jak zpomalit, když dostanete 429.
Limity odesílání
Každý workspace má dva limity odesílání. Nové workspace začínají ve všech tarifech s těmito výchozími hodnotami:
| Limit | Výchozí hodnota | Okno |
|---|---|---|
| Za sekundu | 2 e-maily | Klouzavé jednosekundové okno |
| Za den | 5 000 e-mailů | Kalendářní den v UTC, obnovuje se v 00:00 UTC |
Jak se limity uplatňují:
- Pro každý workspace. Všechny API klíče i SMTP relay sdílejí stejná počítadla. Odesílání přes SMTP čerpá stejný příděl jako API.
- Počítají se příjemci. Každá jedinečná adresa v
to,ccabccje jeden e-mail. Požadavek se třemi příjemci se počítá jako tři. - Počítá se jen odesílání. Limity platí pro Odeslání e-mailu a Přeposlání e-mailu. Čtení dat a správa zdrojů se do nich nepočítají.
- Kontrola předem, započtení potom. Odeslání se přijme, dokud workspace limitu ještě nedosáhl, a jeho příjemci se do počítadel přičtou až potom. Jeden požadavek s mnoha příjemci vás tak může dostat přes limit a další požadavky dostanou
429, dokud se okno nevyprázdní.
Aktuální limity a dnešní využití vidíte v panelu Sending Limits na úvodní stránce Dashboard.
Hlavičky limitů rychlosti
Odpovědi endpointů pro odeslání a přeposlání obsahují tyto hlavičky:
| Hlavička | Popis |
|---|---|
ratelimit-limit |
Kolik e-mailů může workspace odeslat za sekundu. |
ratelimit-remaining |
Kolik e-mailů zbývá v aktuálním jednosekundovém okně. |
ratelimit-reset |
Počet sekund do obnovení okna za sekundu. |
ratelimit-daily-limit |
Kolik e-mailů může workspace odeslat za den. |
ratelimit-daily-remaining |
Kolik e-mailů dnes zbývá. |
ratelimit-daily-reset |
Počet sekund do obnovení denního limitu v 00:00 UTC. |
retry-after |
Počet sekund, které je třeba počkat před dalším pokusem. Posílá se jen s odpověďmi 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: 52113Když narazíte na limit
Odeslání nad limit vrátí 429 Too Many Requests s hlavičkou retry-after. Tělo uvádí, na který limit jste narazili:
{
"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
}| Pole | Popis |
|---|---|
error |
Rate limit exceeded pro limit za sekundu, Daily limit exceeded pro denní limit. |
limit |
Limit, kterého jste dosáhli. |
current |
Kolik e-mailů už bylo v okně započteno. |
retry_after |
Počet sekund, které je třeba počkat. 1 u limitu za sekundu a počet sekund do 00:00 UTC u denního limitu. |
Když se požadavek odmítne, nic se neodešle a nespotřebují se žádné kredity. Odmítnutí kvůli limitu za sekundu zopakujte po krátkém čekání. Při odmítnutí kvůli dennímu limitu e-mail zařaďte do fronty a odešlete ho po obnovení limitu, nebo požádejte o vyšší limit.
Další limity
Několik endpointů má vlastní limity:
| Endpoint | Limit | Počítá se pro |
|---|---|---|
POST /emails/{id}/forward |
3 za hodinu | Workspace |
POST /webhooks/{id}/test |
5 za minutu | IP adresu |
Hostované odkazy pro přihlášení a odhlášení (/subscribe/{token}, /unsubscribe/{token}) |
30 za minutu | IP adresu |
Veřejné endpointy formulářů: načtení formuláře (GET /forms/{token}) |
60 za minutu | IP adresu |
Veřejné endpointy formulářů: odeslání formuláře (POST /forms/{token}/submit) |
30 za minutu | IP adresu |
Přeposlání se navíc počítají do limitů odesílání výše. Po překročení limitu přeposílání vrátí API 429 s hlavičkou retry-after:
{
"error": "too_many_requests",
"message": "Forwarding is limited to 3 emails per hour for this workspace. Try again later."
}Tyto limity jsou pevné a nemění se s tarifem ani s limity odesílání.
Všechny ostatní endpointy
Endpointy, které čtou data nebo spravují zdroje, nemají pevný limit pro jednotlivé endpointy. Používejte je rozumně: posílejte malý počet souběžných požadavků místo tisíců paralelně, data, která se mění zřídka, si ukládejte do mezipaměti a místo opakovaného dotazování na stav e-mailů používejte webhooky.
Navyšte si limity
- Tarify Pro a Business. Limity se při odesílání zvyšují automaticky podle vaší kondice odesílání. Emailit je zvyšuje nejvýše jednou za sedm dní, a to jen pokud je vaše kondice odesílání dobrá a žádná z vašich domén není pozastavená.
- Všechny tarify. O navýšení požádejte na úvodní stránce Dashboard: v panelu Sending Limits vyberte Request Increase, zadejte limity za sekundu a za den, které potřebujete, odkud pochází váš seznam adres a proč navýšení potřebujete. Tým podpory žádosti obvykle posoudí do 24 hodin.
Všechny limity tarifů najdete na stránce Limity.
Opakujte požadavky s rostoucím odstupem
Opakujte odpovědi 429, 409 (idempotenční klíč se právě zpracovává), 500 a 503. Pokud je přítomná hlavička retry-after, počkejte uvedený počet sekund, a pokud není, použijte exponenciálně rostoucí odstup s náhodným rozptylem (jitter). Posílejte hlavičku Idempotency-Key, aby se opakované odeslání nikdy nedoručilo dvakrát, a na obnovení denního limitu nečekejte ve smyčce požadavků.
# 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)Tipy pro velké objemy
- Odesílejte z fronty s pevným počtem pracovních procesů a jejich počet přizpůsobte limitu za sekundu.
- Velké dávkové úlohy rozložte do celého dne, místo abyste je spustili všechny najednou, aby jedna úloha nevyčerpala celý denní příděl.
- Sledujte
ratelimit-daily-remaininga zpomalte dřív, než klesne na nulu. - Na newslettery pro vaše seznamy kontaktů používejte kampaně místo opakovaného volání endpointu pro odeslání.