Rate Limiting & Best Practices
Understand rate limits, tiers, and best practices for efficient API usage.
Rate Limit Tiers
| Tier | Per Minute | Per Day |
|---|---|---|
| Free | 10 requests | 100 requests |
| Pro | 1,000 requests | 10,000 requests |
| Developer | 5,000 requests | 50,000 requests |
| Enterprise | 50,000 requests | 500,000 requests |
How It Works
Rate limiting uses a per-minute sliding window scoped to each API key. Each request decrements the remaining count, which refills continuously as the window slides forward.
- Window: 60-second sliding window
- Scope: Per API key (not per IP or endpoint)
- Daily limits are calculated on a rolling 24-hour basis
Response Headers
Every API response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per minute |
X-RateLimit-Remaining | Remaining requests in current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
HTTP/1.1 200 OK X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 997 X-RateLimit-Reset: 1691452860 X-Request-Id: req_abc123
When Rate Limited (HTTP 429)
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1691452845
{
"success": false,
"data": null,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Retry after 45 seconds.",
"status_code": 429
},
"meta": { "request_id": "req_rate123" }
}
Handling Rate Limits in Code
TypeScript (SDK auto-retry)
import { GenuineInClient } from '@genuinein/sdk';
const client = new GenuineInClient({
apiKey: process.env.GENUINEIN_API_KEY,
retryConfig: {
maxRetries: 3,
retryOn429: true, // Auto-wait on rate limit
backoffMultiplier: 2, // Exponential backoff
}
});
// SDK automatically retries on 429
const results = await client.talent.search({ query: 'react developer' });
Python (manual retry with backoff)
import time, requests
def api_request_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
wait_time = retry_after * (2 ** attempt) # Exponential backoff
print(f"Rate limited. Waiting {wait_time}s (attempt {attempt + 1})")
time.sleep(wait_time)
continue
return response
raise Exception("Max retries exceeded")
Best Practices
1. Respect Remaining Count
Check X-RateLimit-Remaining and slow down before hitting zero.
2. Use Bulk Endpoints
Batch operations save rate limit budget:
| Approach | Requests Used |
|---|---|
100x GET /talent/profiles/{gpin} | 100 requests |
1x POST /talent/bulk-search (100 GPINs) | 1 request |
3. Cache Responses
Profile data doesn't change frequently. Cache responses locally (respect Cache-Control headers) to reduce API calls.
4. Distribute Requests Evenly
Spread requests across the minute window rather than bursting all at once. Use a queue with a delay between requests.
5. Use Webhooks Instead of Polling
Instead of polling for changes, subscribe to webhook events for real-time updates at zero rate limit cost.
Quota Monitoring
Monitor your API usage in the Developer Portal Analytics page, or programmatically:
curl -H "X-API-Key: gin_your_key_here" \ https://api.genuinein.com/api/enterprise/v1/usage/quota
Returns current usage, remaining quota, and reset time for both per-minute and daily limits.