Rate Limits
API rate limiting information
SuperSend API uses two layers of rate limiting:
The sections below give the numbers and how to handle each.
Infrastructure rate limits (V1 and V2)
All API traffic—both V1 and V2—to api.supersend.io, track.supersend.io, and io.supersend.io is subject to the following limits per client IP address:
| Limit | Value | Description |
|---|---|---|
| Requests per second | 50 | Max 50 requests per second per IP |
| Concurrent connections | 20 | Max 20 simultaneous connections per IP |
| Requests per minute | 3,000 | Max 3,000 requests per minute per IP |
These limits are enforced at the load balancer before traffic reaches the application. If you exceed them, you will receive 503 Service Temporarily Unavailable. Clients behind a shared IP (e.g. NAT, corporate proxy) share the same limits.
Endpoint-specific rate limits
V1 API
The V1 API applies additional rate limiting on specific endpoints only:
| Endpoint | Authenticated | Unauthenticated |
|---|---|---|
/v1/guess-email | 10,000/min | 3/min |
/v1/verify-email | 100/sec (paid) | 10/sec (free) |
/v1/generate-summary | 10 per 2 seconds | N/A |
Note: Most V1 endpoints (contact CRUD, campaigns, teams, etc.) do not have rate limiting applied.
V2 API
The V2 API does not apply endpoint-specific rate limits (unlike the V1 endpoints in the table above). V2 traffic is still subject to the infrastructure rate limits (50 req/s, 20 connections, 3,000 req/min per IP). We recommend reasonable request patterns and exponential backoff on 503 to stay within those limits.
Best Practices
To stay within rate limits and keep your integration reliable:
1. Use Bulk Endpoints
Instead of creating contacts one by one, use bulk creation:
// Less efficient - multiple requests
for (const contact of contacts) {
await createContact(contact)
}// More efficient - single request
await fetch('https://api.supersend.io/v1/bulk-contacts', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
contacts: contacts,
TeamId: 'your-team-id',
CampaignId: 'your-campaign-id'
})
})
2. Implement Exponential Backoff
For any errors, implement exponential backoff:
async function apiRequestWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, options)
if (response.ok) return response
// For server errors, retry with backoff
if (response.status >= 500) {
const delay = Math.min(1000 * Math.pow(2, attempt), 30000)
await new Promise(r => setTimeout(r, delay))
continue
}
return response // Client errors shouldn't be retried
} catch (err) {
if (attempt === maxRetries - 1) throw err
const delay = Math.min(1000 * Math.pow(2, attempt), 30000)
await new Promise(r => setTimeout(r, delay))
}
}
}3. Cache Responses
Don't fetch the same data repeatedly:
const cache = new Map()async function getCampaign(id) {
if (cache.has(id)) {
return cache.get(id)
}
const response = await fetch(https://api.supersend.io/v2/campaigns/${id}, {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
})
const campaign = await response.json()
cache.set(id, campaign.data)
// Clear cache after 5 minutes
setTimeout(() => cache.delete(id), 5 60 1000)
return campaign.data
}
4. Use Pagination Efficiently
When fetching large datasets, use appropriate page sizes:
async function getAllContacts(teamId, campaignId) {
const allContacts = []
let offset = 0
const limit = 100
while (true) {
const response = await fetch(
https://api.supersend.io/v2/contacts?TeamId=${teamId}&CampaignId=${campaignId}&limit=${limit}&offset=${offset},
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
)
const data = await response.json()
allContacts.push(...data.data)
if (!data.pagination.has_more) break
offset += limit
}
return allContacts
}When you hit a rate limit
| Limit type | HTTP status | Response body | What to do |
|---|---|---|---|
| Infrastructure (too many requests/sec, too many connections, or too many requests/min for your IP) | 503 | None | Back off and retry with exponential backoff. Reduce concurrency or request rate. |
| Endpoint (e.g. guess-email, verify-email over their per-endpoint cap) | 429 | JSON with rate_limit_error or rate_limit_exceeded | Wait for the limit window to reset, then retry. |
503 from infrastructure: The load balancer returns 503 before your request reaches the API. There is no JSON body—only the status code. Use exponential backoff and avoid retrying immediately.
429 from endpoint limits: The API returns a normal error payload. Example (V2 format):
{
"error": {
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "Too many requests. Please retry after the limit window resets.",
"doc_url": "https://docs.supersend.io/docs/rate-limits"
},
"request_id": "req_a1b2c3d4e5f6789012345678"
}For full error shapes and codes, see Error Handling.
Need Higher Throughput?
For enterprise customers with specific throughput requirements, contact support@supersend.io to discuss your use case.