# Límites de velocidad

> Cómo limita Emailit el envío por espacio de trabajo, las cabeceras ratelimit de cada envío, qué aspecto tiene un 429, los límites de otros endpoints y cómo reintentar con espera exponencial.

Emailit limita la velocidad y el volumen de envío de un espacio de trabajo, no el número de llamadas a la API que haces. Esta página explica los límites de envío, las cabeceras que los indican, los pocos endpoints con límites propios y cómo esperar antes de reintentar cuando recibes un `429`.

## Límites de envío

Cada espacio de trabajo tiene dos límites de envío. Los espacios de trabajo nuevos empiezan con estos valores por defecto en todos los planes:

| Límite | Por defecto | Ventana |
| --- | --- | --- |
| Por segundo | 2 emails | Ventana deslizante de un segundo |
| Al día | 5000 emails | Día natural en UTC; se restablece a las 00:00 UTC |

Cómo se aplican los límites:

- **Por espacio de trabajo.** Todas las claves de API y el [SMTP relay](/es/docs/smtp/) comparten los mismos contadores. Enviar por SMTP consume la misma cuota que la API.
- **Se cuentan por destinatarios.** Cada dirección única entre `to`, `cc` y `bcc` es un email. Una petición con tres destinatarios cuenta como tres.
- **Solo cuentan los envíos.** Los límites se aplican a [Enviar un email](/es/docs/api-reference/emails/send/) y [Reenviar un email](/es/docs/api-reference/emails/forward/). Leer datos y gestionar recursos no cuenta para ellos.
- **Se comprueban antes y se cuentan después.** Un envío se acepta siempre que el espacio de trabajo no haya alcanzado aún el límite, y sus destinatarios se suman a los contadores después. Una sola petición con muchos destinatarios puede hacer que superes el límite, y las peticiones siguientes reciben `429` hasta que se libera la ventana.

Puedes ver los límites actuales y el uso de hoy en la tarjeta **Sending Limits** de la página de inicio de **Dashboard**.

## Cabeceras de límite de velocidad

Las respuestas de los endpoints de envío y de reenvío incluyen estas cabeceras:

| Cabecera | Descripción |
| --- | --- |
| `ratelimit-limit` | Emails que el espacio de trabajo puede enviar por segundo. |
| `ratelimit-remaining` | Emails que quedan en la ventana actual de un segundo. |
| `ratelimit-reset` | Segundos que faltan para que se restablezca la ventana por segundo. |
| `ratelimit-daily-limit` | Emails que el espacio de trabajo puede enviar al día. |
| `ratelimit-daily-remaining` | Emails que quedan hoy. |
| `ratelimit-daily-reset` | Segundos que faltan para que el límite diario se restablezca a las 00:00 UTC. |
| `retry-after` | Segundos que hay que esperar antes de reintentar. Solo se envía con las respuestas `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
```

## Cuando alcanzas un límite

Un envío que supera el límite devuelve `429 Too Many Requests` con una cabecera `retry-after`. El cuerpo indica qué límite has alcanzado:

**429 Por segundo**

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

**429 Diario**

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

| Campo | Descripción |
| --- | --- |
| `error` | `Rate limit exceeded` para el límite por segundo, `Daily limit exceeded` para el límite diario. |
| `limit` | El límite que se ha alcanzado. |
| `current` | Cuántos emails se habían contado ya en la ventana. |
| `retry_after` | Segundos que hay que esperar. `1` para el límite por segundo, y los segundos que faltan hasta las 00:00 UTC para el límite diario. |

Cuando se rechaza una petición, no se envía nada y no se gastan créditos. Reintenta los rechazos por segundo tras una breve espera. En los rechazos diarios, pon el email en cola y envíalo después del restablecimiento, o solicita un límite más alto.

## Otros límites

Algunos endpoints tienen límites propios:

| Endpoint | Límite | Se cuenta por |
| --- | --- | --- |
| `POST /emails/{id}/forward` | 3 por hora | Espacio de trabajo |
| `POST /webhooks/{id}/test` | 5 por minuto | Dirección IP |
| Enlaces alojados de suscripción y de baja (`/subscribe/{token}`, `/unsubscribe/{token}`) | 30 por minuto | Dirección IP |
| Endpoints públicos de formularios: cargar un formulario (`GET /forms/{token}`) | 60 por minuto | Dirección IP |
| Endpoints públicos de formularios: enviar un formulario (`POST /forms/{token}/submit`) | 30 por minuto | Dirección IP |

Los reenvíos también cuentan para los límites de envío anteriores. Si superas el límite de reenvíos, la API devuelve `429` con una cabecera `retry-after`:

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

Estos límites son fijos y no cambian con tu plan ni con tus límites de envío.

## Todos los demás endpoints

Los endpoints que leen datos o gestionan recursos no tienen un límite fijo por endpoint. Haz un uso razonable: usa un pool pequeño de peticiones simultáneas en lugar de miles en paralelo, guarda en caché los datos que cambian poco y usa [webhooks](/es/docs/webhooks/) en lugar de consultar periódicamente el estado de los emails.

## Aumentar tus límites

- **Pro y Business.** Los límites suben automáticamente a medida que envías, según tu [salud de envío](/es/docs/deliverability/sending-health/). Emailit los aumenta como máximo una vez cada siete días, y solo mientras tu salud de envío sea buena y ninguno de tus dominios esté pausado.
- **Todos los planes.** Solicita un aumento en la página de inicio de **Dashboard**: selecciona **Request Increase** en la tarjeta **Sending Limits** e indica los límites por segundo y diarios que necesitas, de dónde procede tu lista y por qué. El equipo de soporte suele revisar las solicitudes en 24 horas.

Para ver todos los límites de cada plan, consulta [Límites](/es/docs/limits/).

## Reintentar con espera exponencial

Reintenta las respuestas `429`, `409` (clave de idempotencia en curso), `500` y `503`. Espera los segundos que indique `retry-after` cuando la cabecera esté presente y, si no, usa una espera exponencial con variación aleatoria (jitter). Envía una [`Idempotency-Key`](/es/docs/api-reference/idempotency/) para que un envío reintentado nunca se entregue dos veces, y no esperes a que pase un límite diario dentro de un bucle de peticiones.

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

## Consejos para grandes volúmenes

- Envía desde una cola con un número fijo de workers y ajusta el tamaño del pool a tu límite por segundo.
- Reparte los trabajos por lotes grandes a lo largo del día en lugar de lanzarlos todos a la vez, para que un solo trabajo no consuma toda la cuota diaria.
- Vigila `ratelimit-daily-remaining` y reduce el ritmo antes de que llegue a cero.
- Para enviar newsletters a tus listas de contactos, usa [campañas](/es/docs/campaigns/) en lugar de llamar al endpoint de envío en un bucle.

## Ver también

  - [Límites](/es/docs/limits/): Límites de envío y cuotas de los planes en un solo lugar.
  - [Salud de envío](/es/docs/deliverability/sending-health/): La puntuación que determina los aumentos automáticos de los límites.
  - [Idempotencia](/es/docs/api-reference/idempotency/): Reintenta envíos sin enviar dos veces.
  - [Errores](/es/docs/api-reference/errors/): Todos los formatos de error y códigos de estado.

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