Referência
Limites de requisições
Como o Emailit limita o envio por workspace, os cabeçalhos ratelimit de cada envio, como é uma resposta 429, os limites de outros endpoints e como tentar de novo com backoff.
O Emailit limita a velocidade e a quantidade de envio de um workspace, não o número de chamadas à API que você faz. Esta página explica os limites de envio, os cabeçalhos que os informam, os poucos endpoints com limites próprios e como aplicar backoff quando você recebe um 429.
Limites de envio
Todo workspace tem dois limites de envio. Workspaces novos começam com estes valores padrão em todos os planos:
| Limite | Padrão | Janela |
|---|---|---|
| Por segundo | 2 e-mails | Janela deslizante de um segundo |
| Por dia | 5.000 e-mails | Dia do calendário em UTC, reiniciado às 00:00 UTC |
Como os limites se aplicam:
- Por workspace. Todas as chaves de API e o SMTP relay compartilham os mesmos contadores. Enviar por SMTP consome a mesma cota que a API.
- Contados por destinatário. Cada endereço único em
to,ccebccé um e-mail. Uma requisição com três destinatários conta como três. - Só os envios contam. Os limites se aplicam a Enviar um e-mail e Encaminhar um e-mail. Ler dados e gerenciar recursos não conta para eles.
- Verificado antes, contado depois. Um envio é aceito desde que o workspace ainda não tenha atingido o limite, e os destinatários dele são somados aos contadores depois. Uma única requisição com muitos destinatários pode levar você além do limite, e as requisições seguintes recebem
429até a janela ser liberada.
Você pode ver os limites atuais e o uso de hoje no card Sending Limits da página inicial do Dashboard.
Cabeçalhos de limite de requisições
As respostas dos endpoints de envio e de encaminhamento incluem estes cabeçalhos:
| Cabeçalho | Descrição |
|---|---|
ratelimit-limit |
E-mails que o workspace pode enviar por segundo. |
ratelimit-remaining |
E-mails restantes na janela de um segundo atual. |
ratelimit-reset |
Segundos até a janela por segundo ser reiniciada. |
ratelimit-daily-limit |
E-mails que o workspace pode enviar por dia. |
ratelimit-daily-remaining |
E-mails restantes hoje. |
ratelimit-daily-reset |
Segundos até o limite diário ser reiniciado, às 00:00 UTC. |
retry-after |
Segundos a esperar antes de tentar de novo. Enviado apenas com respostas 429. |
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: 52113Quando você atinge um limite
Um envio acima do limite retorna 429 Too Many Requests com um cabeçalho retry-after. O corpo indica qual limite foi atingido:
{
"error": "Rate limit exceeded",
"message": "Too many requests. Maximum 2 messages per second allowed.",
"limit": 2,
"current": 2,
"retry_after": 1
}{
"error": "Daily limit exceeded",
"message": "Daily sending limit of 5000 messages has been reached.",
"limit": 5000,
"current": 5000,
"retry_after": 41760
}| Campo | Descrição |
|---|---|
error |
Rate limit exceeded para o limite por segundo, Daily limit exceeded para o limite diário. |
limit |
O limite que foi atingido. |
current |
Quantos e-mails já foram contados na janela. |
retry_after |
Segundos a esperar. 1 para o limite por segundo e, para o limite diário, os segundos até 00:00 UTC. |
Quando uma requisição é rejeitada, nada é enviado e nenhum crédito é usado. Tente de novo as rejeições do limite por segundo após uma breve espera. Para as rejeições do limite diário, coloque o e-mail na fila e envie-o depois da reinicialização, ou peça um limite maior.
Outros limites
Alguns endpoints têm limites próprios:
| Endpoint | Limite | Contado por |
|---|---|---|
POST /emails/{id}/forward |
3 por hora | Workspace |
POST /webhooks/{id}/test |
5 por minuto | Endereço IP |
Links hospedados de inscrição e de descadastro (/subscribe/{token}, /unsubscribe/{token}) |
30 por minuto | Endereço IP |
Endpoints públicos de formulário: carregar um formulário (GET /forms/{token}) |
60 por minuto | Endereço IP |
Endpoints públicos de formulário: enviar um formulário (POST /forms/{token}/submit) |
30 por minuto | Endereço IP |
Os encaminhamentos também contam para os limites de envio acima. Acima do limite de encaminhamentos, a API retorna 429 com um cabeçalho retry-after:
{
"error": "too_many_requests",
"message": "Forwarding is limited to 3 emails per hour for this workspace. Try again later."
}Esses limites são fixos e não mudam com o seu plano nem com os seus limites de envio.
Todos os outros endpoints
Os endpoints que leem dados ou gerenciam recursos não têm um limite fixo por endpoint. Mantenha o seu uso razoável: use um pequeno pool de requisições simultâneas em vez de milhares em paralelo, guarde em cache os dados que raramente mudam e use webhooks em vez de consultar periodicamente o status dos e-mails.
Aumentar os seus limites
- Pro e Business. Os limites aumentam automaticamente à medida que você envia, com base na sua saúde de envio. O Emailit os aumenta no máximo uma vez a cada sete dias, e apenas enquanto a sua saúde de envio estiver boa e nenhum dos seus domínios estiver pausado.
- Todos os planos. Peça um aumento na página inicial do Dashboard: selecione Request Increase no card Sending Limits e informe os limites por segundo e por dia de que você precisa, de onde vem a sua lista e o motivo. A equipe de suporte normalmente analisa as solicitações em até 24 horas.
Consulte Limites para ver todos os limites dos planos.
Tentar de novo com backoff
Tente de novo as respostas 429, 409 (chave de idempotência em uso), 500 e 503. Aguarde retry-after segundos quando o cabeçalho estiver presente e use backoff exponencial com jitter quando ele não estiver. Envie um Idempotency-Key para que um envio repetido nunca seja entregue duas vezes, e não espere o fim de um limite diário em um loop de requisições.
# 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."
}'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);
}
}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)Dicas para alto volume
- Envie a partir de uma fila com um número fixo de workers e dimensione o pool de acordo com o seu limite por segundo.
- Distribua grandes jobs em lote ao longo do dia em vez de iniciar todos de uma vez, para que um único job não consuma toda a cota diária.
- Acompanhe
ratelimit-daily-remaininge reduza o ritmo antes que ele chegue a zero. - Para newsletters para as suas listas de contatos, use campanhas em vez de chamar o endpoint de envio em um loop.