# Idempotence

> Relancez les envois d’e-mails sans risque avec l’en-tête Idempotency-Key. Endpoints pris en charge, format et portée des clés, fenêtre de rejeu de 24 heures et erreurs associées.

Après une erreur réseau ou un timeout, vous ne savez pas si un envoi a abouti. Une clé d’idempotence permet de relancer l’envoi sans risque : si Emailit a déjà accepté une requête avec la même clé, il renvoie la réponse d’origine au lieu d’envoyer à nouveau l’e-mail. Cette page est la référence de l’en-tête `Idempotency-Key`. Pour un guide pas à pas, consultez [Envois idempotents](/fr/docs/email-api/idempotency/).

## Endpoints pris en charge

| Endpoint | |
| --- | --- |
| `POST /emails` | [Envoyer un e-mail](/fr/docs/api-reference/emails/send/) |
| `POST /emails/{id}/forward` | [Transférer un e-mail](/fr/docs/api-reference/emails/forward/) |

Les autres endpoints ignorent l’en-tête. La création d’un domaine, d’une clé API, d’une liste de contacts ou d’un contact peut déjà être relancée sans risque : une deuxième requête avec le même nom ou la même adresse e-mail renvoie `409` et l’objet `existing` au lieu de créer un doublon.

## Envoyer une clé

Ajoutez un en-tête `Idempotency-Key` dont la valeur est propre à l’e-mail que vous envoyez, comme un UUID ou un ID issu de votre propre système :

**cURL**

```bash
curl https://api.emailit.com/v2/emails \
  -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",
    "html": "<p>Thanks for your order.</p>"
  }'
```

**Node.js**

```javascript
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': `order-${order.id}-confirmation`,
  },
  body: JSON.stringify({
    from: 'Acme <orders@acme.com>',
    to: order.email,
    subject: `Your order #${order.id}`,
    html: '<p>Thanks for your order.</p>',
  }),
});
```

**Python**

```python
import os
import requests

response = requests.post(
    "https://api.emailit.com/v2/emails",
    headers={
        "Authorization": f"Bearer {os.environ['EMAILIT_API_KEY']}",
        "Idempotency-Key": f"order-{order['id']}-confirmation",
    },
    json={
        "from": "Acme <orders@acme.com>",
        "to": order["email"],
        "subject": f"Your order #{order['id']}",
        "html": "<p>Thanks for your order.</p>",
    },
    timeout=30,
)
```

Générez la clé une seule fois par e-mail, avant la première tentative, et envoyez la même clé à chaque relance de cet e-mail.

## Fonctionnement des clés

| Règle | Détails |
| --- | --- |
| Format | De 1 à 256 caractères. Lettres, chiffres, traits d’union (`-`) et tirets bas (`_`) uniquement. |
| Portée | Par espace de travail. Les clés de différents espaces de travail n’entrent jamais en collision, mais les deux endpoints partagent le même espace de noms : ne réutilisez donc pas une clé d’envoi pour un transfert. |
| Durée de vie | La réponse à une requête réussie est conservée 24 heures après la fin de la requête. |
| Rejeux | Une requête avec une clé enregistrée renvoie la réponse enregistrée avec le statut `200`. Aucun e-mail n’est envoyé, aucun crédit n’est consommé et les limites d’envoi ne sont pas décomptées. |
| Correspondance | Seule la clé est comparée, pas le corps de la requête. Une requête différente avec une clé déjà utilisée renvoie la première réponse. |
| Échecs | Si une requête échoue, quelle que soit l’erreur, rien n’est enregistré et la clé est libérée : vous pouvez corriger la requête et la relancer avec la même clé. |
| Simultanéité | Tant qu’une requête avec une clé est en cours, une autre requête avec la même clé renvoie `409`. Le verrou est libéré lorsque la première requête se termine, et il expire au bout de 15 minutes au maximum. |

Une requête rejouée passe quand même par l’authentification et par la vérification des [limites d’envoi](/fr/docs/api-reference/rate-limits/) par seconde et quotidienne : elle peut donc renvoyer `401` ou `429`. Les transferts sont aussi décomptés de la limite horaire de transferts, même lorsque la réponse est rejouée.

## Erreurs

**400**

```json
{
  "error": "Invalid Idempotency-Key"
}
```

**409**

```json
{
  "error": "Idempotency key in progress",
  "message": "A request with this Idempotency-Key is already being processed. Retry shortly with the same key."
}
```

**503**

```json
{
  "error": "Idempotency unavailable",
  "message": "Unable to process Idempotency-Key right now. Retry the request with the same key."
}
```

| Statut | `error` | Cause | Que faire |
| --- | --- | --- | --- |
| `400` | `Invalid Idempotency-Key` | La clé est vide, dépasse 256 caractères ou contient d’autres caractères que des lettres, des chiffres, `-` et `_`. | Utilisez un UUID ou une autre valeur sûre. |
| `409` | `Idempotency key in progress` | Une requête avec la même clé est encore en cours de traitement. | Patientez une seconde, puis relancez avec la même clé. Vous obtiendrez la réponse enregistrée dès que la première requête sera terminée. |
| `503` | `Idempotency unavailable` | Emailit ne peut pas vérifier la clé pour le moment. La requête n’a pas été traitée. | Relancez avec la même clé après un court délai. |

Emailit ne traite jamais une requête sans vérifier son idempotence : si la clé ne peut pas être vérifiée, la requête échoue avec `503` plutôt que de risquer un doublon.

## Choisir de bonnes clés

- Dérivez la clé de l’objet de la notification, comme `order-1042-confirmation` ou `password-reset-<token-id>`, pour qu’une relance depuis un autre worker ou après un redémarrage utilise la même clé.
- N’utilisez un nouvel UUID que si l’e-mail n’a pas d’identifiant naturel, et enregistrez-le avec la tâche avant la première tentative.
- Ne réutilisez pas une clé pour un autre e-mail dans les 24 heures. Vous obtiendriez la réponse du premier e-mail et le second ne serait pas envoyé.

## Voir aussi

  - [Envois idempotents](/fr/docs/email-api/idempotency/): Un guide pour envoyer sans risque de doublon en cas de relance.
  - [Limites de débit](/fr/docs/api-reference/rate-limits/): Espacez vos requêtes et relancez-les, avec un exemple de code.

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