Skip to main content
Lettr enforces per-team rate limits on API requests to prevent any single integration from overwhelming the service. Rate limits control how many API requests you can make within a time window.
Rate limits are different from email quotas. Rate limits control API request frequency (requests per second), while email quotas control sending volume (emails per month). For details on monthly email quotas, daily sending limits, and how usage is tracked, see Email Usage & Quotas.

API Rate Limits

The default rate limit is 3 requests per second per team, shared across all API keys belonging to the same team. If you exceed the limit, subsequent requests return a 429 status until the window resets.
Limit TypeValue
API requests3 requests per second
Authentication failures5 failures / 5 minutes (15 min block)

Email Sending Limits

LimitValue
Recipients per request50 (combined to, cc, bcc)
Monthly email quotaBased on your plan
Daily email limit100 (free tier only)

Rate Limit Response Headers

Every API response includes headers that let you track your rate limit status in real time. Use these to pace your requests and avoid hitting the limit:
HeaderDescription
X-RateLimit-LimitMaximum number of requests allowed per second.
X-RateLimit-RemainingHow many requests you have left in the current window.
X-RateLimit-ResetUnix timestamp (in seconds) when the rate limit window resets.
Retry-AfterHow many seconds to wait before retrying. Only present on 429 responses.

Rate Limit Error Response

When you exceed rate limits, you’ll receive a 429 Too Many Requests response with the rate_limit_exceeded error code:
{
  "message": "Rate limit exceeded. Please slow down your requests.",
  "error_code": "rate_limit_exceeded"
}
The response includes a Retry-After header indicating how many seconds to wait before retrying.

Sending Quota Headers

The Send Email endpoint returns additional headers that track your daily and monthly email quotas. These headers are present for free tier teams:
HeaderDescription
X-Daily-LimitMaximum number of emails you can send per day.
X-Daily-RemainingHow many emails you have left today.
X-Daily-ResetUnix timestamp when the daily counter resets (midnight UTC).
X-Monthly-LimitMaximum number of emails you can send per billing month.
X-Monthly-RemainingHow many emails you have left this month.
X-Monthly-ResetUnix timestamp when the monthly counter resets.
For full details on these headers, see the API Reference — Rate Limit.

Handling Rate Limits

When you receive a 429 response, use the Retry-After header to determine how long to wait. Implement exponential backoff as a fallback:
async function sendWithBackoff(emailData, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await lettr.emails.send(emailData);
    } catch (error) {
      if (error.status === 429) {
        const retryAfter = error.retryAfter || Math.pow(2, attempt);
        console.log(`Rate limited. Retrying in ${retryAfter} seconds...`);
        await sleep(retryAfter * 1000);
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}

Batch Sending with Rate Limiting

When sending to large recipient lists, pace your API calls to stay within rate limits. Adding a short delay between batches prevents bursts that trigger throttling:
const recipients = [...]; // Large list
const batchSize = 50;
const delayBetweenBatches = 500; // milliseconds

for (let i = 0; i < recipients.length; i += batchSize) {
  const batch = recipients.slice(i, i + batchSize);

  await lettr.emails.send({
    from: 'you@example.com',
    to: batch,
    subject: 'Newsletter',
    html: content
  });

  // Pace your requests
  if (i + batchSize < recipients.length) {
    await sleep(delayBetweenBatches);
  }
}

Monthly Email Quotas

Your monthly email quota depends on your plan:
PlanMonthly Emails
Free3,000
Pro 50K50,000
Pro 100K100,000
Pro 200K200,000
Pro 500K500,000
Pro 1M1,000,000
EnterpriseCustom
Emails beyond your tier limit are charged at $0.80 per 1,000 emails. See Billing for details.

Best Practices

Always implement exponential backoff for 429 responses. Use the Retry-After header from the response when available, and fall back to a 2^attempt delay otherwise. Without backoff, rapid retries will keep hitting the limit and delay your sends further.
Check the X-RateLimit-Remaining header on every response. When it approaches zero, slow down your request rate proactively instead of waiting for a 429 response.
Each API request supports up to 50 recipients. Sending to 50 recipients per request instead of one-at-a-time reduces your API call count by 50x, making it far easier to stay within rate limits for large sends.
On free tier, check the X-Daily-Remaining and X-Monthly-Remaining headers to track your quota usage in real time. Set up internal alerts at 80% and 90% of your quota so you can upgrade your plan before hitting the limit.
For campaigns targeting thousands of recipients, use a job queue (such as BullMQ, Laravel Queues, or Celery) to pace sending over minutes or hours. This avoids burst patterns that trigger rate limits and gives you better control over delivery timing.
Polling the API to check delivery status consumes rate limit budget. Instead, set up webhooks to receive delivery, bounce, and engagement events asynchronously. This eliminates polling requests entirely and gives you faster, event-driven status updates.

Increasing Your Limits

If your current limits don’t match your sending volume, you have several options:
  • Upgrade your plan — Increases your monthly email quota immediately
  • Enterprise plans — Custom rate limits tailored to your traffic patterns — contact sales to discuss your requirements
  • Batch recipients — Send up to 50 recipients per request to reduce API call volume
  • Use webhooks — Replace polling with event-driven notifications to save rate limit budget
  • Implement a queue — Smooth out traffic spikes to avoid burst patterns

Contact Sales

Need higher limits? Contact our sales team for Enterprise options.