# API Rate Limits

To ensure fair usage and system stability, the DanubeData API implements rate limiting on all endpoints.

## Rate Limit Tiers

Rate limits vary based on your account tier:

| Account Tier | Requests per Minute | Requests per Hour | Requests per Day |
|--------------|---------------------|-------------------|------------------|
| **Free**     | 240                 | 2,000             | 20,000           |
| **Starter**  | 480                 | 6,000             | 100,000          |
| **Professional** | 960             | 20,000            | 400,000          |
| **Enterprise** | 2,000             | 100,000           | 2,000,000        |

## Rate Limit Headers

Every API response includes rate limit information in the headers:

```http
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1699564800
```

### Header Descriptions

- **`X-RateLimit-Limit`**: Maximum requests allowed in the current window
- **`X-RateLimit-Remaining`**: Number of requests remaining in the current window
- **`X-RateLimit-Reset`**: Unix timestamp when the rate limit resets

## Checking Your Rate Limit

### In HTTP Responses

```bash
curl -I -H "Authorization: Bearer YOUR_TOKEN" \
     https://danubedata.ro/api/v1/vps

# Response headers:
# X-RateLimit-Limit: 60
# X-RateLimit-Remaining: 59
# X-RateLimit-Reset: 1699564860
```

### Parsing Rate Limit Headers

```javascript
// JavaScript example
axios.get('/api/v1/vps')
  .then(response => {
    const remaining = response.headers['x-ratelimit-remaining'];
    const reset = response.headers['x-ratelimit-reset'];
    
    console.log(`Requests remaining: ${remaining}`);
    console.log(`Resets at: ${new Date(reset * 1000)}`);
  });
```

```python
# Python example
response = requests.get('/api/v1/vps', headers=headers)

remaining = response.headers.get('X-RateLimit-Remaining')
reset_time = response.headers.get('X-RateLimit-Reset')

print(f"Requests remaining: {remaining}")
print(f"Resets at: {datetime.fromtimestamp(int(reset_time))}")
```

## Rate Limit Exceeded (429)

When you exceed the rate limit, you'll receive a `429 Too Many Requests` response:

```json
{
  "message": "Too Many Requests",
  "retry_after": 45
}
```

### Retry-After Header

The response includes a `Retry-After` header indicating when you can retry (in seconds):

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1699564860
```

## Best Practices

### 1. Implement Exponential Backoff

When receiving a 429 response, wait before retrying:

```javascript
async function makeRequestWithRetry(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await axios.get(url);
      return response.data;
    } catch (error) {
      if (error.response?.status === 429) {
        const retryAfter = error.response.headers['retry-after'] || 60;
        const delay = retryAfter * 1000 * Math.pow(2, i); // Exponential backoff
        
        console.log(`Rate limited. Waiting ${delay}ms before retry...`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}
```

### 2. Monitor Rate Limit Headers

Check remaining requests before making additional calls:

```javascript
function shouldMakeRequest(headers) {
  const remaining = parseInt(headers['x-ratelimit-remaining']);
  const limit = parseInt(headers['x-ratelimit-limit']);
  
  // Stop if less than 10% remaining
  return remaining > (limit * 0.1);
}
```

### 3. Cache Responses

Reduce API calls by caching responses:

```javascript
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getCached(key, fetcher) {
  const cached = cache.get(key);
  
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }
  
  const data = await fetcher();
  cache.set(key, { data, timestamp: Date.now() });
  
  return data;
}

// Usage
const vps = await getCached('vps-list', () => 
  api.get('/vps').then(r => r.data)
);
```

### 4. Batch Requests

Instead of multiple individual requests, use list endpoints:

```bash
# ❌ Bad: Multiple requests
GET /api/v1/vps/vps-123
GET /api/v1/vps/vps-456
GET /api/v1/vps/vps-789

# ✅ Good: Single request
GET /api/v1/vps
```

### 5. Use Webhooks

Instead of polling for changes, configure webhooks:

```bash
# ❌ Bad: Poll every minute
while true; do
  curl /api/v1/vps/vps-123/status
  sleep 60
done

# ✅ Good: Configure webhook once
curl -X PUT /api/v1/webhooks/config \
  -d '{"webhook_url": "https://example.com/webhook"}'
```

## Rate Limit Windows

Rate limits are calculated using sliding windows:

- **Per-Minute**: Rolling 60-second window
- **Per-Hour**: Rolling 60-minute window
- **Per-Day**: Rolling 24-hour window

This means:
- If you make 60 requests at 10:00:00, you can't make more until 10:01:00
- Limits gradually refill as time passes

## Endpoint-Specific Limits

Some endpoints override the tier limits above:

### Higher Limits
- **Health Check** (`/api/v1/health`) - Not rate limited
- **Status Endpoints** (VPS status, cache connection-info, database credentials) - 2x tier limits
- **Storage Metrics** (`/storage/buckets/{id}/metrics`) - 2x tier limits

### Lower Limits
- **Snapshot Creation** - 10/minute, 100/hour, 1,000/day
- **Instance Creation** (VPS, cache, database) - 40/minute, 200/hour, 2,000/day
- **Bucket Creation** - 40/minute, 200/hour, 2,000/day
- **Access Key Creation** - 20/minute, 100/hour, 1,000/day

## Monitoring Usage

### In Your Dashboard

View your API usage:
1. Navigate to **API Tokens**
2. Click on a token to view its usage statistics
3. See graphs of:
   - Requests per hour
   - Rate limit hits
   - Most used endpoints

### Usage Alerts

Set up alerts for:
- Approaching rate limits (80% usage)
- Rate limit exceeded events
- Unusual usage patterns

## Upgrading Your Limits

Your 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.

If your workload needs limits beyond the Professional tier, contact support to discuss an Enterprise tier with higher ceilings and burst capacity.

## Common Scenarios

### Monitoring/Polling

If you need to poll for status updates frequently:

1. **Use webhooks instead** - Best option
2. **Increase polling interval** - Check every 5 minutes instead of every minute
3. **Use efficient status endpoints** - `/status` endpoints use fewer resources

### Bulk Operations

When performing bulk operations:

```javascript
// Add delays between requests
async function processBatch(items) {
  for (const item of items) {
    await processItem(item);
    
    // Wait 1 second between requests to avoid rate limits
    await new Promise(r => setTimeout(r, 1000));
  }
}
```

### CI/CD Pipelines

For automated deployments:

1. Use a dedicated API token with higher priority
2. Implement retry logic with exponential backoff
3. Cache static data (images, SSH keys)
4. Run deployments sequentially, not in parallel

## Troubleshooting

### Consistently Hitting Rate Limits

**Solutions:**
- Implement caching
- Use webhooks instead of polling
- Batch requests where possible
- Upgrade to a higher tier

### 429 Errors in Production

**Immediate Actions:**
1. Check the `Retry-After` header
2. Implement exponential backoff
3. Review recent code changes for inefficient API usage
4. Enable caching if not already enabled

### Rate Limit Headers Missing

If rate limit headers are missing:
- Check you're using API v1 endpoints (`/api/v1/...`)
- Verify authentication is working correctly
- Contact support if the issue persists

## Next Steps

- Visit `/docs/api` to see rate limits for specific endpoints
- Configure webhooks to reduce polling
- Implement caching in your application
- Monitor your API usage in the dashboard

