Skip to main content

Rate Limits

SendSeven limits request rates to keep the platform fast and fair. A request over a limit gets 429 Too Many Requests. Handle every 429 the same way: wait, then retry.

Limits​

Per-endpoint limits​

These endpoints have their own limits, counted per client IP address, whatever authentication you use:

EndpointLimit
POST /api/v1/knowledge-base/documents/crawl10 per minute
POST /api/v1/knowledge-base/documents/recrawl10 per minute
POST /api/v1/knowledge-base/documents/crawl/preview20 per minute
POST /api/v1/knowledge-base/search60 per minute
POST /api/v1/email-providers/{provider_id}/test10 per minute and 50 per hour (per workspace)

General limits​

Every other authenticated request counts against one general limit. Which one depends on how you authenticate:

CredentialLimitCounted per
API keys and OAuth tokens (your own integrations, OAuth apps, the MCP server, Zapier, Make, n8n, the HubSpot embed)3,000 requests per minuteWorkspace
People signed in to the web or mobile app (Bearer JWT sessions, see Authentication)300 requests per minute sustained, bursts of up to 150Person
  • API keys and OAuth tokens share one limit per workspace: all keys and apps of a workspace count together. The workspace is the one the token belongs to, whether or not you send X-Tenant-ID. A parent token with tenants:manage that addresses a sub-account with X-Tenant-ID (see Multi-Tenancy) counts against that sub-account.
  • People each have their own limit, whichever workspace they work in, so the size of your team never matters. A person's activity in the app never uses up your integrations' limit, and integration traffic never slows people down.
  • The limit for people is a token bucket: it holds up to 150 requests, and 5 come back every second (300 per minute). Loading or reloading the app several times in a row fits in the bucket; only a sustained rate above 300 per minute is rejected.

An X-Tenant-ID value the credential may not act for never moves the request to another workspace's limit.

Workspace limits for sending endpoints​

These endpoints count per workspace for every credential, instead of the general limit:

RequestsLimit
/api/v1/email-campaigns/..., /api/v1/invitations/... and POST /api/v1/email-integrations/email-messages/<id>/forward30 per minute per workspace (shared)
/api/v1/double-opt-in/send and /resend10 per minute per workspace

Other limits​

  • Some features have their own limits and answer 429 with an endpoint-specific body, for example WhatsApp template edits (template_edit_limit_reached, see Templates) or AI features.
  • Delivery speed is also limited by each channel provider (for example WhatsApp throughput per number). That shows up in message status and campaign pacing, not as a 429 on your request.

Limits can change. Don't rely on the absence of rate-limit headers: build your client to handle a 429 on any endpoint.

Rate limit headers​

Responses counted against a general or workspace limit carry these headers. They describe the limit the request was counted against, so an API key sees its workspace's 3,000 and a signed-in person the size of their own bucket (150). Requests rejected before the credential is verified, for example with 401, carry none.

X-RateLimit-Limit: 3000
X-RateLimit-Remaining: 2987
X-RateLimit-Reset: 1706889600
HeaderDescription
X-RateLimit-LimitMaximum requests per window (for a signed-in person: the bucket size)
X-RateLimit-RemainingRequests remaining in the current window (for a signed-in person: requests left in the bucket)
X-RateLimit-ResetUnix timestamp when the window resets (for a signed-in person: when the bucket is full again, or on a 429 when the next request is allowed)

When you hit the limit​

A general or workspace limit answers with headers and a JSON body:

HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 3000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1706889600

{
"detail": "Rate limit exceeded. Please slow down.",
"error": "rate_limit_exceeded",
"category": "api_token",
"retry_after": 12
}

category names the limit you hit: api_token (API keys and OAuth tokens, per workspace), ui_user (a signed-in person), email_send or double_opt_in. Treat it as informational and handle every 429 the same way.

A per-endpoint limit answers with a shorter body and no Retry-After header:

HTTP/1.1 429 Too Many Requests

{
"error": "Rate limit exceeded: 10 per 1 minute"
}

Use Retry-After when it is present, otherwise back off exponentially.

Handling rate limits​

import time
import requests

def request_with_backoff(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code != 429:
return response
retry_after = int(response.headers.get("Retry-After", 2 ** attempt))
time.sleep(retry_after)
raise Exception("Max retries exceeded")

Tips to avoid rate limits​

  • Batch requests where possible instead of making individual calls
  • Cache responses for data that doesn't change frequently (contacts, tags)
  • Use webhooks instead of polling for real-time updates
  • Respect Retry-After headers and don't retry immediately