Rate Limits
API request limits and quotas
Rate Limits
NotiGrid enforces rate limits to ensure fair usage and system stability. Understanding these limits helps you build reliable integrations.
Overview
Rate limits restrict:
- API requests per minute - How many API calls you can make
- Notifications per hour - How many notifications you can send
- Concurrent requests - Simultaneous active requests
Current Limits
By Plan
| Plan | API Requests/min | Notifications/hour | Concurrent | Burst |
|---|---|---|---|---|
| Free | 100 | 1,000 | 5 | 120 |
| Starter | 1,000 | 10,000 | 10 | 1,200 |
| Pro | 10,000 | 100,000 | 50 | 12,000 |
| Enterprise | Custom | Custom | Custom | Custom |
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1642435200
X-RateLimit-Resource: notificationsHeaders:
X-RateLimit-Limit- Maximum requests allowed in windowX-RateLimit-Remaining- Requests remaining in current windowX-RateLimit-Reset- Unix timestamp when limit resetsX-RateLimit-Resource- Resource type being limited
Rate Limit Response
When you exceed the rate limit, you'll receive a 429 Too Many Requests response:
{
"error": {
"code": "rate_limit_exceeded",
"message": "API rate limit exceeded",
"retry_after": 45
}
}The Retry-After header indicates seconds until you can retry:
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1642435200Handling Rate Limits
Exponential Backoff
Implement exponential backoff for retries:
async function sendWithRetry(notification, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await sendNotification(notification);
} catch (error) {
if (error.status === 429) {
const retryAfter = error.headers['retry-after'] || Math.pow(2, attempt);
await sleep(retryAfter * 1000);
continue;
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}Python Example
import time
import requests
def send_with_retry(notification, max_retries=3):
for attempt in range(max_retries):
try:
response = requests.post(
'https://api.notigrid.com/v1/notifications',
json=notification,
headers={'Authorization': f'Bearer {API_KEY}'}
)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 429:
retry_after = int(e.response.headers.get('Retry-After', 2 ** attempt))
time.sleep(retry_after)
continue
raise
raise Exception('Max retries exceeded')Burst Limits
Burst limits allow short-term spikes above your rate limit:
- Burst window: 10 seconds
- Burst allowance: 20% above rate limit
Example: If your limit is 1,000/min, you can send up to 1,200 in a 10-second burst.
Concurrency Limits
Maximum simultaneous API requests:
const pLimit = require('p-limit');
// Limit to 10 concurrent requests
const limit = pLimit(10);
const promises = notifications.map(notification =>
limit(() => sendNotification(notification))
);
await Promise.all(promises);Per-Resource Limits
Different endpoints have different limits:
Notification Sending
POST /v1/notifications
Rate limit: Based on plan tierTemplate Management
GET /v1/templates
Rate limit: 1,000/min (all plans)
POST /v1/templates
Rate limit: 100/min (all plans)Analytics & Logs
GET /v1/logs
Rate limit: 500/min (all plans)Best Practices
1. Monitor Rate Limit Headers
Check headers after each request:
function checkRateLimit(response) {
const remaining = response.headers['x-ratelimit-remaining'];
const reset = response.headers['x-ratelimit-reset'];
if (remaining < 10) {
console.warn(`Rate limit low: ${remaining} requests remaining`);
// Slow down requests
}
}2. Use Batch Operations
Send multiple notifications in one request:
POST /v1/notifications/batch
{
"notifications": [
{ "to": "user1@example.com", "template": "welcome" },
{ "to": "user2@example.com", "template": "welcome" },
{ "to": "user3@example.com", "template": "welcome" }
]
}Batch endpoints have higher limits (10,000 notifications per request).
3. Implement Queueing
Use a queue to smooth out traffic:
const Queue = require('bull');
const notificationQueue = new Queue('notifications');
// Add to queue
notificationQueue.add({
to: 'user@example.com',
template: 'welcome'
});
// Process queue with rate limiting
notificationQueue.process(async (job) => {
await sendNotification(job.data);
});4. Cache Responses
Cache frequently accessed data to reduce API calls:
const cache = new Map();
async function getTemplate(name) {
if (cache.has(name)) {
return cache.get(name);
}
const template = await fetchTemplate(name);
cache.set(name, template);
// Expire after 5 minutes
setTimeout(() => cache.delete(name), 5 * 60 * 1000);
return template;
}5. Spread Requests
Distribute requests evenly:
// Bad: Send all at once
for (const user of users) {
await sendNotification(user);
}
// Good: Space out requests
for (const user of users) {
await sendNotification(user);
await sleep(100); // 10 requests/second
}Monitoring
Dashboard
View real-time rate limit usage:
- Go to Dashboard → Analytics
- Select API Usage
- View current usage and trends
Alerts
Set up alerts for high usage:
- Go to Settings → Alerts
- Click Add Alert
- Configure:
- Metric: API Request Rate
- Threshold: 80% of limit
- Recipients: your-email@example.com
- Save
You'll receive an email when approaching limits.
Increasing Limits
Upgrade Plan
Higher plans have higher limits. Compare plans at notigrid.com/pricing.
Request Increase
Contact sales for custom limits:
- Email: sales@notigrid.com
- Include:
- Current plan
- Required limit
- Use case description
Temporary Increase
Need a temporary boost for a campaign?
- Go to Settings → Billing
- Click Request Temporary Increase
- Specify:
- Duration needed
- Expected traffic
- Campaign details
- Submit request
Approval within 24 hours.
Rate Limit Calculator
Estimate your needs:
Hourly notification volume: 10,000 notifications/hour Notifications per minute: 10,000 / 60 = ~167/min With 20% safety margin: 167 * 1.2 = 200/min Recommended plan: Starter (1,000/min)
Error Handling
Complete error handling example:
class RateLimitError extends Error {
constructor(retryAfter) {
super('Rate limit exceeded');
this.retryAfter = retryAfter;
}
}
async function sendNotification(data) {
try {
const response = await fetch('https://api.notigrid.com/v1/notifications', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
throw new RateLimitError(parseInt(retryAfter));
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
return await response.json();
} catch (error) {
if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter}s`);
await sleep(error.retryAfter * 1000);
return sendNotification(data); // Retry
}
throw error;
}
}FAQs
Q: Do rate limits reset at a fixed time? A: No, limits use a sliding window. If you hit the limit at 10:30, it resets at 10:31.
Q: Are failed requests counted against limits? A: Yes, all requests count, including errors.
Q: Can I check my limits programmatically?
A: Yes, use GET /v1/account/limits to retrieve current limits and usage.
Q: What happens if I consistently exceed limits? A: Your account may be temporarily restricted. Contact support if you need higher limits.
Q: Are webhook deliveries rate limited? A: No, webhooks you receive are not counted. Only outgoing API requests.
Support
Questions about rate limits?
- Documentation: docs.notigrid.com/rate-limits
- Support: support@notigrid.com
- Sales: sales@notigrid.com