Rate limits
All limits use a one-minute window.
| Limit | Applies to | Counted per |
|---|---|---|
| 300 requests / minute | Every REST request under /api/v1 (the MCP endpoint and inbound provider webhooks have their own limits) |
Client IP address |
| 10 requests / minute | /api/v1/auth/* (login, refresh, password reset) |
Client IP address |
| 120 requests / minute | The MCP endpoint /mcp |
API key |
| 60 requests / minute | POST /api/v1/leads/bulk and POST /api/v1/leads/bulk/tags |
User |
| 30 requests / minute | Endpoints that send SMS and WhatsApp messages | User |
Public, unauthenticated endpoints have their own small limits — for example, inbound webhook ingest allows 60 requests per minute per IP.
The limits stack: a request to POST /api/v1/leads/bulk counts against both the global per-IP limit and the per-user write limit. MCP calls count only toward the 120/minute per-key limit, not the 300/minute budget. Integrations that share one outbound IP (a NAT gateway, a serverless platform) share the 300/minute budget.
Headers
Section titled “Headers”Responses from limited routes carry the standard RateLimit-* headers:
| Header | Meaning |
|---|---|
RateLimit-Limit |
Requests allowed in the window. |
RateLimit-Remaining |
Requests left in the current window. |
RateLimit-Reset |
Seconds until the window resets. |
When you hit a limit
Section titled “When you hit a limit”The API answers 429 Too Many Requests with a JSON body. The global limit returns:
{ "error": "Too many requests, please try again later." }Other limiters use their own wording — for example /api/v1/auth/* returns "Too many authentication attempts, please try again later." Branch on the 429 status, not on the message.
The MCP endpoint answers in JSON-RPC form instead:
{ "jsonrpc": "2.0", "error": { "code": -32000, "message": "Rate limit exceeded. Please slow down." }, "id": null }Staying under the limits
Section titled “Staying under the limits”- Read
RateLimit-Remainingand slow down before it reaches zero. - On a
429, wait forRateLimit-Resetseconds, then retry. Add jitter when several workers retry at once. - Use
limit=100on list endpoints to fetch more per request (see Pagination). - Use webhooks to learn about changes instead of polling.