# 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](/cs/docs/smtp/) 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`, `cc` a `bcc` je 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](/cs/docs/api-reference/emails/send/) a [Přeposlání e-mailu](/cs/docs/api-reference/emails/forward/). Č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
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
```

## Když 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:

**429 Za sekundu**

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

**429 Denní**

```json
{
  "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`:

```json
{
  "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](/cs/docs/webhooks/).

## Navyšte si limity

- **Tarify Pro a Business.** Limity se při odesílání zvyšují automaticky podle vaší [kondice odesílání](/cs/docs/deliverability/sending-health/). 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](/cs/docs/limits/).

## 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`](/cs/docs/api-reference/idempotency/), aby se opakované odeslání nikdy nedoručilo dvakrát, a na obnovení denního limitu nečekejte ve smyčce požadavků.

**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)
```

## 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-remaining` a zpomalte dřív, než klesne na nulu.
- Na newslettery pro vaše seznamy kontaktů používejte [kampaně](/cs/docs/campaigns/) místo opakovaného volání endpointu pro odeslání.

## Související

  - [Limity](/cs/docs/limits/): Limity odesílání a kvóty tarifů na jednom místě.
  - [Kondice odesílání](/cs/docs/deliverability/sending-health/): Skóre, podle kterého se limity automaticky zvyšují.
  - [Idempotence](/cs/docs/api-reference/idempotency/): Opakujte odeslání, aniž byste e-mail poslali dvakrát.
  - [Chyby](/cs/docs/api-reference/errors/): Všechny formáty chyb a stavové kódy.

---
Zdroj: https://emailit.com/cs/docs/api-reference/rate-limits/
