Misar Docs
MisarMailMisar.BlogMisarReachMisarPostMisar.DevMisar PlatformMisar IdentityMisar Posts API
Api Reference

Rate Limits

Per-endpoint rate limits, 429 responses, and Redis-backed headers

MisarMail enforces two types of limits:

  1. Rate limits — requests per minute per API key (short-term burst protection)
  2. Plan limits — total emails / contacts / etc. per day or month (long-term usage enforcement)

This page covers rate limits. See Plan Limits for usage quotas.

Rate limits are enforced per API key, not per IP address.


Limits by Endpoint

EndpointWindowLimitNotes
POST /v1/send1 minute100 requestsPer API key
GET /v1/contacts1 minute100 requestsPer API key
POST /v1/contacts1 minute60 requestsPer API key
POST /v1/contacts/import1 minute10 requestsPer API key
POST /v1/campaigns1 minute30 requestsPer API key
POST /v1/ai/subject-lines1 minute10 requestsPer API key
POST /v1/validate1 minute30 requestsPer API key
All other /v1/*1 minute60 requestsPer API key (default)

429 Response

When a rate limit is exceeded, the API returns:

HTTP/1.1 429 Too Many Requests
{
  "success": false,
  "error": "Too many requests. Please slow down.",
  "retryAfter": 42
}

retryAfter is the number of seconds until the window resets.

Response Headers

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1708790460
Retry-After: 42

Use the Retry-After header value to schedule your next request rather than polling.


Handling Rate Limits

Always check for 429 and respect Retry-After:

async function sendWithRateLimit(payload: object) {
  const res = await fetch("https://api.misar.io/mail/v1/send", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.MISARMAIL_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
  });

  if (res.status === 429) {
    const data = await res.json();
    const retryAfter = data.retryAfter || 60;
    await new Promise(r => setTimeout(r, retryAfter * 1000));
    return sendWithRateLimit(payload); // retry once
  }

  return res.json();
}

Bulk Operations

For bulk sending (e.g., campaigns to thousands of contacts), use the campaign API instead of calling POST /v1/send in a loop. Campaigns are processed asynchronously by the MisarMail queue, which handles rate limiting, retry logic, and ISP throttling automatically.

// ❌ Don't do this for bulk
for (const contact of contacts) {
  await sendEmail({ to: [contact], ... });
}

// ✅ Use campaigns for bulk
await createAndSendCampaign({ segment_id: "...", template_id: "..." });