Rate Limits
Spamidate enforces three types of limits to ensure fair usage and system stability.
Limit Types
Section titled “Limit Types”| Type | Window | Purpose |
|---|---|---|
| Per-minute | Rolling 60 seconds | Prevent burst abuse |
| Per-day | Calendar day (UTC) | Daily usage cap |
| Per-month | Billing cycle | Total plan quota |
Limits by Tier
Section titled “Limits by Tier”| Tier | Per Minute | Per Day | Per Month | Grace Period |
|---|---|---|---|---|
| Free | 10 | 100 | 100 | None |
| Hobby | 50 | 2,000 | 2,000 | None |
| Growth | 100 | 10,000 | 10,000 | 20% |
| Pro | 500 | 50,000 | 50,000 | 20% |
| Business | 1,000 | 200,000 | 200,000 | 20% |
| Scale | 2,500 | 500,000 | 500,000 | 20% |
| Enterprise | Custom | Custom | Custom | 20% |
Grace Period System
Section titled “Grace Period System”How It Works
Section titled “How It Works”0%────────80%────────100%────────120% │ │ │ │ │ └── Hard stop │ └── Grace period starts └── Normal usage| Usage Range | Behavior |
|---|---|
| 0-80% | Normal operation |
| 80-100% | Warning headers sent |
| 100-120% | Grace period (requests still work) |
| >120% | Hard stop until next cycle |
Free & Hobby Tiers
Section titled “Free & Hobby Tiers”Free and Hobby tiers stop immediately at 100% quota—no grace period. Upgrade to Growth for the buffer.
Response Headers
Section titled “Response Headers”Every response includes rate limit information:
X-RateLimit-Limit-Minute: 100X-RateLimit-Limit-Day: 10000X-RateLimit-Remaining: 88X-RateLimit-Reset: 2024-01-15T10:31:00.000ZX-RateLimit-Used-Month: 4523X-RateLimit-Limit-Month: 10000When Rate Limited
Section titled “When Rate Limited”Status: 429 Too Many Requests
Headers:
Retry-After: 45X-RateLimit-Remaining: 0Body:
{ "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded", "details": { "limit": 100, "window": "minute", "retryAfter": 45 } }}Handling Rate Limits
Section titled “Handling Rate Limits”With the SDK
Section titled “With the SDK”The SDK handles rate limits automatically:
import { Spamidate, RateLimitError } from '@spamidate/sdk';
const client = new Spamidate({ apiKey: process.env.SPAMIDATE_API_KEY, retries: 3, // Automatic retry on rate limit});
// SDK waits for Retry-After automaticallyconst result = await client.validate(email);Manual Retry
Section titled “Manual Retry”async function validateWithRetry(email: string): Promise<Result> { const response = await fetch('https://api.spamidate.com/validate', { method: 'POST', headers: { 'X-API-Key': process.env.SPAMIDATE_API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ email }), });
if (response.status === 429) { const retryAfter = parseInt(response.headers.get('Retry-After') || '60'); await new Promise(r => setTimeout(r, retryAfter * 1000)); return validateWithRetry(email); }
return response.json();}Optimization Tips
Section titled “Optimization Tips”1. Use Batch Validation
Section titled “1. Use Batch Validation”One API call for up to 100 emails:
// Instead of 100 separate callsconst results = await client.validateBatch(emails.slice(0, 100));2. Cache Results
Section titled “2. Cache Results”Validation results are stable—cache for 24 hours:
const cache = new Map();
async function validate(email: string) { const key = email.toLowerCase(); if (cache.has(key)) return cache.get(key);
const result = await client.validate(email); cache.set(key, result); return result;}3. Use Quick Mode
Section titled “3. Use Quick Mode”Skip expensive checks when speed matters:
// Real-time form validationconst quick = await client.validate(email, { quickMode: true });
// Background processing - full validationconst full = await client.validate(email);4. Deduplicate Before Batch
Section titled “4. Deduplicate Before Batch”const unique = [...new Set(emails.map(e => e.toLowerCase()))];const results = await client.validateBatch(unique);Monitoring Usage
Section titled “Monitoring Usage”Dashboard
Section titled “Dashboard”View real-time usage at spamidate.com/dashboard.
const usage = await client.getUsage();
console.log(`${usage.quota.percentage}% used`);console.log(`${usage.quota.remaining} remaining`);console.log(`${usage.period.daysRemaining} days left`);Do cached results count against quota? No. Server-side caching is free—each unique validation counts once.
Does batch count as 1 or 100 requests? Each email counts toward quota, but it’s one rate limit request.
Can I get a temporary quota increase? Enterprise plans can request increases. Contact support.
Do failed validations count? Yes. Any processed request counts (even invalid emails).
How do I check quota without using it?
Use GET /api/usage—this endpoint is free.