{"slug":"api-rate-limits","title":"API Rate Limits","description":"To ensure fair usage and system stability, the DanubeData API implements rate limiting on all endpoints.","section":"API Reference","url":"https://docs.danubedata.ro/api-rate-limits","markdown_url":"https://docs.danubedata.ro/api-rate-limits.md","breadcrumbs":[{"title":"API Reference","slug":null},{"title":"Rate Limits","slug":"api-rate-limits"}],"headings":[{"level":1,"title":"API Rate Limits","id":"api-rate-limits"},{"level":2,"title":"Rate Limit Tiers","id":"rate-limit-tiers"},{"level":2,"title":"Rate Limit Headers","id":"rate-limit-headers"},{"level":3,"title":"Header Descriptions","id":"header-descriptions"},{"level":2,"title":"Checking Your Rate Limit","id":"checking-your-rate-limit"},{"level":3,"title":"In HTTP Responses","id":"in-http-responses"},{"level":3,"title":"Parsing Rate Limit Headers","id":"parsing-rate-limit-headers"},{"level":2,"title":"Rate Limit Exceeded (429)","id":"rate-limit-exceeded-429"},{"level":3,"title":"Retry-After Header","id":"retry-after-header"},{"level":2,"title":"Best Practices","id":"best-practices"},{"level":3,"title":"1. Implement Exponential Backoff","id":"1-implement-exponential-backoff"},{"level":3,"title":"2. Monitor Rate Limit Headers","id":"2-monitor-rate-limit-headers"},{"level":3,"title":"3. Cache Responses","id":"3-cache-responses"},{"level":3,"title":"4. Batch Requests","id":"4-batch-requests"},{"level":3,"title":"5. Use Webhooks","id":"5-use-webhooks"},{"level":2,"title":"Rate Limit Windows","id":"rate-limit-windows"},{"level":2,"title":"Endpoint-Specific Limits","id":"endpoint-specific-limits"},{"level":3,"title":"Higher Limits","id":"higher-limits"},{"level":3,"title":"Lower Limits","id":"lower-limits"},{"level":2,"title":"Monitoring Usage","id":"monitoring-usage"},{"level":3,"title":"In Your Dashboard","id":"in-your-dashboard"},{"level":3,"title":"Usage Alerts","id":"usage-alerts"},{"level":2,"title":"Upgrading Your Limits","id":"upgrading-your-limits"},{"level":2,"title":"Common Scenarios","id":"common-scenarios"},{"level":3,"title":"Monitoring/Polling","id":"monitoringpolling"},{"level":3,"title":"Bulk Operations","id":"bulk-operations"},{"level":3,"title":"CI/CD Pipelines","id":"cicd-pipelines"},{"level":2,"title":"Troubleshooting","id":"troubleshooting"},{"level":3,"title":"Consistently Hitting Rate Limits","id":"consistently-hitting-rate-limits"},{"level":3,"title":"429 Errors in Production","id":"429-errors-in-production"},{"level":3,"title":"Rate Limit Headers Missing","id":"rate-limit-headers-missing"},{"level":2,"title":"Next Steps","id":"next-steps"}],"format":"markdown","word_count":976,"content":"# API Rate Limits\n\nTo ensure fair usage and system stability, the DanubeData API implements rate limiting on all endpoints.\n\n## Rate Limit Tiers\n\nRate limits vary based on your account tier:\n\n| Account Tier | Requests per Minute | Requests per Hour | Requests per Day |\n|--------------|---------------------|-------------------|------------------|\n| **Free**     | 240                 | 2,000             | 20,000           |\n| **Starter**  | 480                 | 6,000             | 100,000          |\n| **Professional** | 960             | 20,000            | 400,000          |\n| **Enterprise** | 2,000             | 100,000           | 2,000,000        |\n\n## Rate Limit Headers\n\nEvery API response includes rate limit information in the headers:\n\n```http\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 45\nX-RateLimit-Reset: 1699564800\n```\n\n### Header Descriptions\n\n- **`X-RateLimit-Limit`**: Maximum requests allowed in the current window\n- **`X-RateLimit-Remaining`**: Number of requests remaining in the current window\n- **`X-RateLimit-Reset`**: Unix timestamp when the rate limit resets\n\n## Checking Your Rate Limit\n\n### In HTTP Responses\n\n```bash\ncurl -I -H \"Authorization: Bearer YOUR_TOKEN\" \\\n     https://danubedata.ro/api/v1/vps\n\n# Response headers:\n# X-RateLimit-Limit: 60\n# X-RateLimit-Remaining: 59\n# X-RateLimit-Reset: 1699564860\n```\n\n### Parsing Rate Limit Headers\n\n```javascript\n// JavaScript example\naxios.get('/api/v1/vps')\n  .then(response => {\n    const remaining = response.headers['x-ratelimit-remaining'];\n    const reset = response.headers['x-ratelimit-reset'];\n    \n    console.log(`Requests remaining: ${remaining}`);\n    console.log(`Resets at: ${new Date(reset * 1000)}`);\n  });\n```\n\n```python\n# Python example\nresponse = requests.get('/api/v1/vps', headers=headers)\n\nremaining = response.headers.get('X-RateLimit-Remaining')\nreset_time = response.headers.get('X-RateLimit-Reset')\n\nprint(f\"Requests remaining: {remaining}\")\nprint(f\"Resets at: {datetime.fromtimestamp(int(reset_time))}\")\n```\n\n## Rate Limit Exceeded (429)\n\nWhen you exceed the rate limit, you'll receive a `429 Too Many Requests` response:\n\n```json\n{\n  \"message\": \"Too Many Requests\",\n  \"retry_after\": 45\n}\n```\n\n### Retry-After Header\n\nThe response includes a `Retry-After` header indicating when you can retry (in seconds):\n\n```http\nHTTP/1.1 429 Too Many Requests\nRetry-After: 45\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 0\nX-RateLimit-Reset: 1699564860\n```\n\n## Best Practices\n\n### 1. Implement Exponential Backoff\n\nWhen receiving a 429 response, wait before retrying:\n\n```javascript\nasync function makeRequestWithRetry(url, maxRetries = 3) {\n  for (let i = 0; i < maxRetries; i++) {\n    try {\n      const response = await axios.get(url);\n      return response.data;\n    } catch (error) {\n      if (error.response?.status === 429) {\n        const retryAfter = error.response.headers['retry-after'] || 60;\n        const delay = retryAfter * 1000 * Math.pow(2, i); // Exponential backoff\n        \n        console.log(`Rate limited. Waiting ${delay}ms before retry...`);\n        await new Promise(resolve => setTimeout(resolve, delay));\n      } else {\n        throw error;\n      }\n    }\n  }\n  throw new Error('Max retries exceeded');\n}\n```\n\n### 2. Monitor Rate Limit Headers\n\nCheck remaining requests before making additional calls:\n\n```javascript\nfunction shouldMakeRequest(headers) {\n  const remaining = parseInt(headers['x-ratelimit-remaining']);\n  const limit = parseInt(headers['x-ratelimit-limit']);\n  \n  // Stop if less than 10% remaining\n  return remaining > (limit * 0.1);\n}\n```\n\n### 3. Cache Responses\n\nReduce API calls by caching responses:\n\n```javascript\nconst cache = new Map();\nconst CACHE_TTL = 5 * 60 * 1000; // 5 minutes\n\nasync function getCached(key, fetcher) {\n  const cached = cache.get(key);\n  \n  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {\n    return cached.data;\n  }\n  \n  const data = await fetcher();\n  cache.set(key, { data, timestamp: Date.now() });\n  \n  return data;\n}\n\n// Usage\nconst vps = await getCached('vps-list', () => \n  api.get('/vps').then(r => r.data)\n);\n```\n\n### 4. Batch Requests\n\nInstead of multiple individual requests, use list endpoints:\n\n```bash\n# ❌ Bad: Multiple requests\nGET /api/v1/vps/vps-123\nGET /api/v1/vps/vps-456\nGET /api/v1/vps/vps-789\n\n# ✅ Good: Single request\nGET /api/v1/vps\n```\n\n### 5. Use Webhooks\n\nInstead of polling for changes, configure webhooks:\n\n```bash\n# ❌ Bad: Poll every minute\nwhile true; do\n  curl /api/v1/vps/vps-123/status\n  sleep 60\ndone\n\n# ✅ Good: Configure webhook once\ncurl -X PUT /api/v1/webhooks/config \\\n  -d '{\"webhook_url\": \"https://example.com/webhook\"}'\n```\n\n## Rate Limit Windows\n\nRate limits are calculated using sliding windows:\n\n- **Per-Minute**: Rolling 60-second window\n- **Per-Hour**: Rolling 60-minute window\n- **Per-Day**: Rolling 24-hour window\n\nThis means:\n- If you make 60 requests at 10:00:00, you can't make more until 10:01:00\n- Limits gradually refill as time passes\n\n## Endpoint-Specific Limits\n\nSome endpoints override the tier limits above:\n\n### Higher Limits\n- **Health Check** (`/api/v1/health`) - Not rate limited\n- **Status Endpoints** (VPS status, cache connection-info, database credentials) - 2x tier limits\n- **Storage Metrics** (`/storage/buckets/{id}/metrics`) - 2x tier limits\n\n### Lower Limits\n- **Snapshot Creation** - 10/minute, 100/hour, 1,000/day\n- **Instance Creation** (VPS, cache, database) - 40/minute, 200/hour, 2,000/day\n- **Bucket Creation** - 40/minute, 200/hour, 2,000/day\n- **Access Key Creation** - 20/minute, 100/hour, 1,000/day\n\n## Monitoring Usage\n\n### In Your Dashboard\n\nView your API usage:\n1. Navigate to **API Tokens**\n2. Click on a token to view its usage statistics\n3. See graphs of:\n   - Requests per hour\n   - Rate limit hits\n   - Most used endpoints\n\n### Usage Alerts\n\nSet up alerts for:\n- Approaching rate limits (80% usage)\n- Rate limit exceeded events\n- Unusual usage patterns\n\n## Upgrading Your Limits\n\nYour API rate limit tier follows your account plan — moving to a higher plan raises the per-minute, per-hour, and per-day ceilings in the [tier table](#rate-limit-tiers). For example, the Starter tier roughly doubles the Free per-minute limit, and Professional roughly quadruples it.\n\nIf your workload needs limits beyond the Professional tier, contact support to discuss an Enterprise tier with higher ceilings and burst capacity.\n\n## Common Scenarios\n\n### Monitoring/Polling\n\nIf you need to poll for status updates frequently:\n\n1. **Use webhooks instead** - Best option\n2. **Increase polling interval** - Check every 5 minutes instead of every minute\n3. **Use efficient status endpoints** - `/status` endpoints use fewer resources\n\n### Bulk Operations\n\nWhen performing bulk operations:\n\n```javascript\n// Add delays between requests\nasync function processBatch(items) {\n  for (const item of items) {\n    await processItem(item);\n    \n    // Wait 1 second between requests to avoid rate limits\n    await new Promise(r => setTimeout(r, 1000));\n  }\n}\n```\n\n### CI/CD Pipelines\n\nFor automated deployments:\n\n1. Use a dedicated API token with higher priority\n2. Implement retry logic with exponential backoff\n3. Cache static data (images, SSH keys)\n4. Run deployments sequentially, not in parallel\n\n## Troubleshooting\n\n### Consistently Hitting Rate Limits\n\n**Solutions:**\n- Implement caching\n- Use webhooks instead of polling\n- Batch requests where possible\n- Upgrade to a higher tier\n\n### 429 Errors in Production\n\n**Immediate Actions:**\n1. Check the `Retry-After` header\n2. Implement exponential backoff\n3. Review recent code changes for inefficient API usage\n4. Enable caching if not already enabled\n\n### Rate Limit Headers Missing\n\nIf rate limit headers are missing:\n- Check you're using API v1 endpoints (`/api/v1/...`)\n- Verify authentication is working correctly\n- Contact support if the issue persists\n\n## Next Steps\n\n- Visit `/docs/api` to see rate limits for specific endpoints\n- Configure webhooks to reduce polling\n- Implement caching in your application\n- Monitor your API usage in the dashboard\n\n","prev":{"title":"Object Storage","slug":"api-storage","url":"https://docs.danubedata.ro/api-storage","markdown_url":"https://docs.danubedata.ro/api-storage.md","json_url":"https://docs.danubedata.ro/api-storage.json"},"next":{"title":"Platform Automation & Diagnostics","slug":"platform-automation","url":"https://docs.danubedata.ro/platform-automation","markdown_url":"https://docs.danubedata.ro/platform-automation.md","json_url":"https://docs.danubedata.ro/platform-automation.json"},"index_url":"https://docs.danubedata.ro/index.json"}