# Limites de débit

> Comment Emailit limite l’envoi par espace de travail, les en-têtes ratelimit de chaque envoi, l’aspect d’une réponse 429, les autres limites des endpoints et comment relancer avec un intervalle exponentiel.

Emailit limite la vitesse et le volume d’envoi d’un espace de travail, pas le nombre d’appels API que vous effectuez. Cette page présente les limites d’envoi, les en-têtes qui les indiquent, les quelques endpoints qui ont leurs propres limites et la façon d’espacer vos requêtes lorsque vous recevez une réponse `429`.

## Limites d’envoi

Chaque espace de travail a deux limites d’envoi. Les nouveaux espaces de travail démarrent avec ces valeurs par défaut, quel que soit le forfait :

| Limite | Par défaut | Fenêtre |
| --- | --- | --- |
| Par seconde | 2 e-mails | Fenêtre glissante d’une seconde |
| Par jour | 5 000 e-mails | Jour calendaire en UTC, réinitialisé à 0 h 00 UTC |

Application des limites :

- **Par espace de travail.** Toutes les clés API et le [relais SMTP](/fr/docs/smtp/) partagent les mêmes compteurs. Un envoi via SMTP consomme le même quota que l’API.
- **Décompte par destinataire.** Chaque adresse unique dans `to`, `cc` et `bcc` compte pour un e-mail. Une requête avec trois destinataires compte pour trois.
- **Seuls les envois comptent.** Les limites s’appliquent à [Envoyer un e-mail](/fr/docs/api-reference/emails/send/) et à [Transférer un e-mail](/fr/docs/api-reference/emails/forward/). La lecture de données et la gestion des ressources ne sont pas décomptées.
- **Vérification avant, décompte après.** Un envoi est accepté tant que l’espace de travail n’a pas encore atteint la limite, et ses destinataires sont ajoutés aux compteurs ensuite. Une seule requête avec de nombreux destinataires peut vous faire dépasser la limite : les requêtes suivantes reçoivent alors `429` jusqu’à ce que la fenêtre se libère.

Les limites actuelles et la consommation du jour s’affichent dans la carte **Sending Limits** de la page d’accueil **Dashboard**.

## En-têtes de limite de débit

Les réponses des endpoints d’envoi et de transfert comportent ces en-têtes :

| En-tête | Description |
| --- | --- |
| `ratelimit-limit` | Nombre d’e-mails que l’espace de travail peut envoyer par seconde. |
| `ratelimit-remaining` | Nombre d’e-mails restants dans la fenêtre d’une seconde en cours. |
| `ratelimit-reset` | Secondes avant la réinitialisation de la fenêtre par seconde. |
| `ratelimit-daily-limit` | Nombre d’e-mails que l’espace de travail peut envoyer par jour. |
| `ratelimit-daily-remaining` | Nombre d’e-mails restants aujourd’hui. |
| `ratelimit-daily-reset` | Secondes avant la réinitialisation de la limite quotidienne, à 0 h 00 UTC. |
| `retry-after` | Secondes à attendre avant de relancer. Envoyé uniquement avec les réponses `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
```

## Lorsque vous atteignez une limite

Un envoi au-delà de la limite renvoie `429 Too Many Requests` avec un en-tête `retry-after`. Le corps indique quelle limite vous avez atteinte :

**429 Par seconde**

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

**429 Quotidienne**

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

| Champ | Description |
| --- | --- |
| `error` | `Rate limit exceeded` pour la limite par seconde, `Daily limit exceeded` pour la limite quotidienne. |
| `limit` | La limite atteinte. |
| `current` | Le nombre d’e-mails déjà décomptés dans la fenêtre. |
| `retry_after` | Secondes à attendre. `1` pour la limite par seconde, et le nombre de secondes jusqu’à 0 h 00 UTC pour la limite quotidienne. |

Lorsqu’une requête est rejetée, rien n’est envoyé et aucun crédit n’est consommé. Relancez les requêtes rejetées par la limite par seconde après une courte attente. En cas de rejet par la limite quotidienne, mettez l’e-mail en file d’attente et envoyez-le après la réinitialisation, ou demandez une limite plus élevée.

## Autres limites

Quelques endpoints ont leurs propres limites :

| Endpoint | Limite | Décompte par |
| --- | --- | --- |
| `POST /emails/{id}/forward` | 3 par heure | Espace de travail |
| `POST /webhooks/{id}/test` | 5 par minute | Adresse IP |
| Liens d’inscription et de désinscription hébergés (`/subscribe/{token}`, `/unsubscribe/{token}`) | 30 par minute | Adresse IP |
| Endpoints publics des formulaires : chargement d’un formulaire (`GET /forms/{token}`) | 60 par minute | Adresse IP |
| Endpoints publics des formulaires : envoi d’un formulaire (`POST /forms/{token}/submit`) | 30 par minute | Adresse IP |

Les transferts sont aussi décomptés des limites d’envoi ci-dessus. Au-delà de la limite de transferts, l’API renvoie `429` avec un en-tête `retry-after` :

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

Ces limites sont fixes et ne varient pas selon votre forfait ni vos limites d’envoi.

## Tous les autres endpoints

Les endpoints qui lisent des données ou gèrent des ressources n’ont pas de limite fixe par endpoint. Gardez un usage raisonnable : utilisez un petit nombre de requêtes simultanées plutôt que des milliers en parallèle, mettez en cache les données qui changent rarement, et utilisez des [webhooks](/fr/docs/webhooks/) plutôt que d’interroger régulièrement l’API pour connaître le statut des e-mails.

## Augmenter vos limites

- **Pro et Business.** Les limites augmentent automatiquement à mesure que vous envoyez, en fonction de votre [santé d’envoi](/fr/docs/deliverability/sending-health/). Emailit les augmente au plus une fois tous les sept jours, et uniquement tant que votre santé d’envoi est bonne et qu’aucun de vos domaines n’est en pause.
- **Tous les forfaits.** Demandez une hausse depuis la page d’accueil **Dashboard** : sélectionnez **Request Increase** dans la carte **Sending Limits**, puis saisissez les limites par seconde et par jour dont vous avez besoin, la provenance de votre liste et la raison de votre demande. L’équipe support examine généralement les demandes sous 24 heures.

Pour toutes les limites des forfaits, consultez [Limites](/fr/docs/limits/).

## Relancer avec un intervalle exponentiel

Relancez les requêtes qui renvoient `429`, `409` (clé d’idempotence en cours d’utilisation), `500` et `503`. Attendez `retry-after` secondes lorsque l’en-tête est présent, et utilisez sinon un intervalle exponentiel avec une part d’aléatoire (jitter). Envoyez une [`Idempotency-Key`](/fr/docs/api-reference/idempotency/) pour qu’un envoi relancé ne soit jamais livré deux fois, et n’attendez pas la fin d’une limite quotidienne dans une boucle de requêtes.

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

## Conseils pour les gros volumes

- Envoyez depuis une file d’attente avec un nombre fixe de workers, et dimensionnez le pool selon votre limite par seconde.
- Répartissez les gros traitements par lots sur la journée au lieu de les lancer tous en même temps, pour qu’une seule tâche ne consomme pas tout le quota quotidien.
- Surveillez `ratelimit-daily-remaining` et ralentissez avant qu’il n’atteigne zéro.
- Pour les newsletters destinées à vos listes de contacts, utilisez les [campagnes](/fr/docs/campaigns/) plutôt qu’une boucle sur l’endpoint d’envoi.

## Voir aussi

  - [Limites](/fr/docs/limits/): Limites d’envoi et quotas des forfaits au même endroit.
  - [Santé d’envoi](/fr/docs/deliverability/sending-health/): Le score qui détermine les hausses automatiques de limite.
  - [Idempotence](/fr/docs/api-reference/idempotency/): Relancez les envois sans envoyer deux fois.
  - [Erreurs](/fr/docs/api-reference/errors/): Tous les formats d’erreur et codes de statut.

---
Source: https://emailit.com/fr/docs/api-reference/rate-limits/
