Rate Limiting
Rate limiting protects the Solatis API from abuse and ensures fair resource usage.
Understanding Rate Limits
Rate limits vary by plan and are applied per API key:
| Plan | Requests/Minute | Requests/Day | Concurrent Requests |
|---|---|---|---|
| Individual | 60 | 10,000 | 5 |
| Team | 300 | 100,000 | 25 |
| Enterprise | Custom | Custom | Custom |
Example:
- Individual plan: 60 requests/minute means ~1 request per second
- If you exceed this, requests are rate limited (HTTP 429)
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1643808000| Header | Meaning |
|---|---|
| X-RateLimit-Limit | Maximum requests/minute for your key |
| X-RateLimit-Remaining | How many requests left in current minute |
| X-RateLimit-Reset | Unix timestamp when limit resets |
Check Rate Limits Before Making Requests
JavaScript:
const checkRateLimit = async () => {
const response = await fetch(
'https://api.solatis.team/v2/documents',
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
}
}
);
const limit = response.headers.get('X-RateLimit-Limit');
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
console.log(`Limit: ${limit}`);
console.log(`Remaining: ${remaining}`);
console.log(`Resets at: ${new Date(reset * 1000).toISOString()}`);
return {
limit: parseInt(limit),
remaining: parseInt(remaining),
resetAt: new Date(reset * 1000)
};
};Python:
import requests
response = requests.get(
'https://api.solatis.team/v2/documents',
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
limit = response.headers.get('X-RateLimit-Limit')
remaining = response.headers.get('X-RateLimit-Remaining')
reset = response.headers.get('X-RateLimit-Reset')
print(f'Limit: {limit}')
print(f'Remaining: {remaining}')
print(f'Resets at: {reset}')Handling 429 Rate Limited Response
When rate limited, you receive HTTP 429:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded",
"retry_after": 60
}
}The X-RateLimit-Reset header tells you when to retry.
Implement Exponential Backoff
JavaScript:
const makeRequestWithRetry = async (
url,
options,
maxRetries = 5,
baseDelay = 1000
) => {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, options);
// Handle rate limiting
if (response.status === 429) {
const retryAfter = response.headers.get('X-RateLimit-Reset');
const waitTime = (retryAfter * 1000) - Date.now();
console.log(`Rate limited. Retrying in ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
if (attempt === maxRetries - 1) throw error;
// Exponential backoff: 1s, 2s, 4s, 8s, 16s
const delay = baseDelay * Math.pow(2, attempt);
console.log(`Attempt ${attempt + 1} failed. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
};
// Usage
const data = await makeRequestWithRetry(
'https://api.solatis.team/v2/documents/analyze',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
document_url: 'https://example.com/contract.pdf'
})
}
);Python:
import requests
import time
import math
def make_request_with_retry(
url,
method='GET',
headers=None,
json=None,
max_retries=5,
base_delay=1
):
"""Make request with exponential backoff retry"""
for attempt in range(max_retries):
try:
if method == 'GET':
response = requests.get(url, headers=headers)
elif method == 'POST':
response = requests.post(url, headers=headers, json=json)
else:
response = requests.request(method, url, headers=headers, json=json)
# Handle rate limiting
if response.status_code == 429:
retry_after = int(response.headers.get('X-RateLimit-Reset', 60))
wait_time = (retry_after * 1000) - (time.time() * 1000)
print(f'Rate limited. Retrying in {wait_time}ms...')
time.sleep(wait_time / 1000)
continue
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
if attempt == max_retries - 1:
raise
# Exponential backoff
delay = base_delay * (2 ** attempt)
print(f'Attempt {attempt + 1} failed. Retrying in {delay}s...')
time.sleep(delay)
# Usage
data = make_request_with_retry(
'https://api.solatis.team/v2/documents/analyze',
method='POST',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
json={'document_url': 'https://example.com/contract.pdf'}
)Staying Within Limits
1. Track Your Usage
Monitor your API usage to avoid hitting limits:
const trackUsage = async (operation) => {
const response = await fetch(
'https://api.solatis.team/v2/documents',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const remaining = parseInt(
response.headers.get('X-RateLimit-Remaining')
);
const percentUsed = ((60 - remaining) / 60) * 100;
console.log(`Rate limit usage: ${percentUsed.toFixed(1)}%`);
// Log operation
console.log(`[${operation}] Remaining requests: ${remaining}`);
return remaining;
};2. Batch Operations
Instead of making individual requests, batch them:
// ❌ BAD - Individual requests (uses 5 requests)
const documents = ['doc1', 'doc2', 'doc3', 'doc4', 'doc5'];
for (const doc of documents) {
await client.documents.analyze(doc);
}
// ✅ GOOD - Batch request (uses 1 request)
const results = await client.documents.analyzeBatch(documents);3. Cache Results
Cache API responses to avoid repeated requests:
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
const getDocumentWithCache = async (docId) => {
const cached = cache.get(docId);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
console.log('Returning cached result');
return cached.data;
}
const data = await client.documents.get(docId);
cache.set(docId, {
data,
timestamp: Date.now()
});
return data;
};4. Implement Request Queuing
Queue requests instead of making them all at once:
const pLimit = require('p-limit');
// Limit to 10 concurrent requests
const limit = pLimit(10);
const documents = [...]; // 1000 documents
const tasks = documents.map(doc =>
limit(() => client.documents.analyze(doc))
);
const results = await Promise.all(tasks);5. Schedule Batch Jobs
For large operations, use background jobs:
// Schedule job to run at off-peak hours
const schedule = require('node-schedule');
// Run at 2 AM every night
schedule.scheduleJob('0 2 * * *', async () => {
console.log('Running batch analysis...');
const allDocuments = await fetchAllDocuments();
// Process in batches of 100
for (let i = 0; i < allDocuments.length; i += 100) {
const batch = allDocuments.slice(i, i + 100);
await processBatch(batch);
// Small delay between batches
await new Promise(resolve => setTimeout(resolve, 1000));
}
});Monitoring and Alerts
Set Up Usage Alerts
Track current usage:
const monitorUsage = async () => {
setInterval(async () => {
const response = await fetch(
'https://api.solatis.team/v2/documents',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const limit = parseInt(response.headers.get('X-RateLimit-Limit'));
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
const used = limit - remaining;
const percentUsed = (used / limit) * 100;
console.log(`Usage: ${used}/${limit} (${percentUsed.toFixed(1)}%)`);
// Alert if > 80% used
if (percentUsed > 80) {
sendAlert(`API rate limit usage: ${percentUsed.toFixed(1)}%`);
}
}, 60000); // Check every minute
};Dashboard Integration
View API usage in your dashboard:
- Go to Settings → Developer → API Analytics
- See requests/minute, requests/day
- View breakdown by endpoint
- See peak usage times
Plan Upgrades
If you consistently hit rate limits, upgrade your plan:
| Action | Impact |
|---|---|
| Individual → Team | 5x more requests/minute (60 → 300) |
| Team → Enterprise | Custom limits (unlimited) |
Upgrade:
- Settings → Billing → Plans
- Click "Upgrade"
- Select new plan
- New limits apply immediately
Advanced Rate Limiting
Sliding Window
Solatis uses sliding window rate limiting:
Minute 0:00 - Requests: 0 (limit: 60)
Minute 0:30 - Requests: 40 (limit: 60) ✅ OK
Minute 0:45 - Requests: 60 (limit: 60) ✅ OK
Minute 1:00 - Request 61 (limit: 60) ❌ Rate limited!
Minute 1:15 - Requests: 55 (as old requests expire) ✅ Can continueRequest Weighting
Some endpoints consume more rate limit:
| Endpoint | Cost |
|---|---|
| GET /documents | 1 request |
| POST /documents/analyze | 5 requests (heavy computation) |
| POST /transcribe | 10 requests (complex processing) |
| GET /documents/:id | 1 request |
Plan accordingly when using heavy endpoints.
Troubleshooting
Hitting Limits Too Quickly
Check:
- Are you polling too frequently?
- Are you making duplicate requests?
- Are you caching results?
- Should you batch operations?
Solutions:
- Increase time between requests
- Implement caching
- Use webhooks instead of polling
- Batch multiple operations
Uneven Rate Limit Usage
Issue: Using all requests at wrong times
Solution:
// Distribute requests evenly throughout minute
const delay = 60000 / requestsPerMinute; // e.g., 1000ms for 60 req/min
setInterval(makeRequest, delay);Upgrading But Still Limited
Check:
- Is the new API key using upgraded plan?
- Did you update your code to use new key?
- Are there multiple keys hitting the limit?
Next Steps
- Code Examples - Retry implementation examples
- Error Handling - Handle all error types
- Getting Started - First request tutorial