Rate Limits
Per-key rate-limit tiers, the 429 response, and the headers MisarReach returns so you can back off correctly.
Rate limits protect the MisarReach API from bursts. They are separate from plan limits — a plan limit caps how much of a feature you may use in a billing period; a rate limit caps how fast you may call the API. For plan/credit limits, see Plans & Limits.
Base URL: https://api.misar.io/reach/api · Rate limits are enforced per API key.
Tiers
Each operation in the contract carries an x-rate-limit-tier. Two tiers exist:
| Tier | Applies to | Behavior |
|---|---|---|
api | Higher-cost or write-heavy operations — all of Lead Finder, campaign enqueue, contacts segments, workspaces, and the LinkedIn ads audience | Throttled per key; exceeding the window returns 429 |
| (none) | Everyday read/write operations — most of deals, pipeline, channels, autopilot, sales-agent, settings, conversations, and core contacts | Not tier-throttled; still subject to your plan limits |
The api-tier ops are the credit-spending and batch endpoints (search, discover, enrich, verify, score, export, enqueue, audience-build). Pace those; the untiered CRUD endpoints are effectively bounded by your plan.
The 429 response
When a key exceeds its window, MisarReach returns 429 Too Many Requests with the standard Error envelope and a retryAfter field:
{
"error": "Rate limit exceeded",
"success": false,
"retryAfter": 12
}Response headers
Every rate-limited response carries these headers — read them to pace requests before you hit the wall:
| Header | Meaning |
|---|---|
Retry-After | Seconds to wait before the next request. |
X-RateLimit-Limit | Requests allowed in the current window. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | Epoch milliseconds when the window resets. |
429 from a rate limit has no plan_limit_exceeded code and no upgrade object — that distinguishes it from a plan/credit limit, which also uses 429/402. Branch on retryAfter / Retry-After for rate limits; branch on code === "plan_limit_exceeded" for plan limits.
Handling it
Retry with exponential backoff, honoring Retry-After:
async function callWithRetry(url: string, init: RequestInit, max = 5): Promise<Response> {
for (let attempt = 0; ; attempt++) {
const res = await fetch(url, init);
if (res.status !== 429 || attempt >= max) return res;
const retryAfter = Number(res.headers.get("Retry-After") ?? 2 ** attempt);
await new Promise((r) => setTimeout(r, retryAfter * 1000));
}
}Every official SDK already retries 429 and 5xx with backoff (honoring Retry-After) — you only need this if you call the REST API directly.
Status page
If you see sustained 429s that don't match your own call rate, check status.misar.io.