# Idempotencia

> Reintenta envíos de emails de forma segura con la cabecera Idempotency-Key. Qué endpoints la admiten, el formato y el ámbito de la clave, la ventana de repetición de 24 horas y sus errores.

Los errores de red y los tiempos de espera agotados te dejan sin saber si un envío se ha completado. Una clave de idempotencia permite reintentar el envío de forma segura: si Emailit ya aceptó una petición con la misma clave, devuelve la respuesta original en lugar de volver a enviar el email. Esta página es la referencia de la cabecera `Idempotency-Key`. Para una guía paso a paso, consulta [Envíos idempotentes](/es/docs/email-api/idempotency/).

## Endpoints compatibles

| Endpoint | |
| --- | --- |
| `POST /emails` | [Enviar un email](/es/docs/api-reference/emails/send/) |
| `POST /emails/{id}/forward` | [Reenviar un email](/es/docs/api-reference/emails/forward/) |

Los demás endpoints ignoran la cabecera. Crear un dominio, una clave de API, una lista de contactos o un contacto ya se puede reintentar de forma segura: una segunda petición con el mismo nombre o email devuelve `409` y el objeto `existing` en lugar de crear un duplicado.

## Enviar una clave

Añade una cabecera `Idempotency-Key` con un valor único para el email que envías, como un UUID o un ID de tu propio sistema:

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

Genera la clave una vez por email, antes del primer intento, y envía la misma clave en cada reintento de ese email.

## Cómo funcionan las claves

| Regla | Detalles |
| --- | --- |
| Formato | De 1 a 256 caracteres. Solo letras, dígitos, guiones (`-`) y guiones bajos (`_`). |
| Ámbito | Por espacio de trabajo. Las claves de distintos espacios de trabajo nunca colisionan, pero los dos endpoints comparten un mismo espacio de nombres, así que no reutilices una clave de envío para un reenvío. |
| Duración | La respuesta a una petición correcta se conserva durante 24 horas desde que termina. |
| Repeticiones | Una petición con una clave almacenada devuelve la respuesta almacenada con el estado `200`. No se envía ningún email, no se gastan créditos y no se suma a los límites de envío. |
| Coincidencia | Solo se compara la clave, no el cuerpo de la petición. Una petición distinta con una clave ya usada devuelve la primera respuesta. |
| Fallos | Si una petición falla con cualquier error, no se almacena nada y la clave se libera, así que puedes corregir la petición y reintentarla con la misma clave. |
| Concurrencia | Mientras una petición con una clave sigue en curso, otra petición con la misma clave devuelve `409`. El bloqueo se libera cuando termina la primera petición y caduca, como máximo, a los 15 minutos. |

Una petición repetida sigue pasando por la autenticación y por la comprobación de los [límites de envío](/es/docs/api-reference/rate-limits/) por segundo y diarios, así que puede devolver `401` o `429`. Los reenvíos también cuentan para el límite de reenvíos por hora, aunque la respuesta sea una repetición.

## Errores

**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."
}
```

| Estado | `error` | Causa | Qué hacer |
| --- | --- | --- | --- |
| `400` | `Invalid Idempotency-Key` | La clave está vacía, tiene más de 256 caracteres o contiene caracteres distintos de letras, dígitos, `-` y `_`. | Usa un UUID u otro valor seguro. |
| `409` | `Idempotency key in progress` | Todavía se está procesando una petición con la misma clave. | Espera un segundo y reintenta con la misma clave. Recibirás la respuesta almacenada cuando termine la primera petición. |
| `503` | `Idempotency unavailable` | Emailit no puede comprobar la clave en este momento. La petición no se ha procesado. | Reintenta con la misma clave tras una breve espera. |

Emailit nunca envía una petición sin su comprobación de idempotencia: si no puede comprobar la clave, la petición falla con `503` en lugar de arriesgarse a un duplicado.

## Elegir buenas claves

- Deriva la clave de aquello sobre lo que notificas, como `order-1042-confirmation` o `password-reset-<token-id>`, para que un reintento desde otro worker o tras un reinicio use la misma clave.
- Usa un UUID nuevo solo cuando el email no tenga un ID natural, y guárdalo con la tarea antes del primer intento.
- No reutilices una clave para otro email en un plazo de 24 horas. Recibirías la respuesta del primer email y el segundo no se enviaría.

## Ver también

  - [Envíos idempotentes](/es/docs/email-api/idempotency/): Guía para enviar con reintentos seguros.
  - [Límites de velocidad](/es/docs/api-reference/rate-limits/): Espera y reintenta, con código de ejemplo.

---
Fuente: https://emailit.com/es/docs/api-reference/idempotency/
