Rate Limiting
:::caution Planned — not yet available
This page describes an API-wide rate-limiting scheme that is not yet implemented. The public REST API does not currently return X-RateLimit-* headers or 429 responses for general endpoints; 429 is used today only by streaming (SSE) endpoints and billing spend-limits. The limits, headers, and examples below illustrate a planned feature.
:::
The Tourfold API implements rate limiting to ensure fair usage and maintain service quality for all users. Understanding and properly handling rate limits is crucial for building reliable applications.
How Rate Limiting Works
Rate limits are applied per API key or user token and are tracked using a sliding window approach. Different endpoints may have different limits based on their resource intensity.
Rate Limit Headers
Every API response includes rate limit information in the headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1642233600
X-RateLimit-Window: 3600
| Header | Description |
|---|---|
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 current window resets |
X-RateLimit-Window | Window size in seconds |
Rate Limit Tiers
| Tier | Requests per Hour | Burst Limit | Description |
|---|---|---|---|
| Standard | 1,000 | 1,000 | Production applications |
| Enterprise | Custom | Custom | Custom limits for enterprise customers |
Default Limits
General Endpoints
- Read operations: 1,000 requests per hour
- Write operations: 500 requests per hour
- Search operations: 200 requests per hour
Specific Endpoint Limits
| Endpoint | Limit | Window | Notes |
|---|---|---|---|
GET /api/v2/tours | 1,000 | 1 hour | List tours |
POST /api/v2/tours | 500 | 1 hour | Create tour |
GET /api/v2/drivers | 1,000 | 1 hour | List drivers |
Handling Rate Limits
Rate Limit Response
When you exceed the rate limit, you'll receive a 429 Too Many Requests response:
{
"type": "https://tourfold.com/problems/rate-limit-exceeded",
"title": "Rate limit exceeded",
"detail": "You have exceeded the rate limit for this endpoint",
"data": {
"limit": 1000,
"remaining": 0,
"reset_time": 1642233600,
"retry_after": 3600,
"window_size": 3600
}
}
Retry After Header
The response also includes a Retry-After header indicating when you can make requests again:
Retry-After: 3600
Best Practices
Implementing Exponential Backoff
#!/bin/bash
make_api_request() {
local url="$1"
local retries="${2:-3}"
response=$(curl -s -w "%{http_code}" -o /tmp/response.json "$url")
http_code="${response: -3}"
if [ "$http_code" -eq 429 ]; then
retry_after=$(curl -s -I "$url" | grep -i "retry-after" | cut -d' ' -f2 | tr -d '\r')
if [ "$retries" -gt 0 ]; then
echo "Rate limited. Waiting $retry_after seconds before retry..."
sleep "$retry_after"
make_api_request "$url" $((retries - 1))
else
echo "Max retries exceeded"
exit 1
fi
else
cat /tmp/response.json
fi
}
# Usage example
make_api_request "https://api.tourfold.com/api/v2/tours" 3
Monitoring Rate Limits
#!/bin/bash
check_rate_limit() {
local url="$1"
# Make a request and capture headers
response=$(curl -s -I -H "Authorization: Bearer YOUR_TOKEN" "$url")
# Extract rate limit headers
limit=$(echo "$response" | grep -i "x-ratelimit-limit" | cut -d' ' -f2 | tr -d '\r')
remaining=$(echo "$response" | grep -i "x-ratelimit-remaining" | cut -d' ' -f2 | tr -d '\r')
reset=$(echo "$response" | grep -i "x-ratelimit-reset" | cut -d' ' -f2 | tr -d '\r')
if [ -n "$limit" ] && [ -n "$remaining" ]; then
usage_percentage=$(( (limit - remaining) * 100 / limit ))
echo "Rate Limit Usage: ${usage_percentage}%"
echo "Remaining: $remaining / $limit"
echo "Reset: $(date -d @$reset)"
if [ "$usage_percentage" -gt 80 ]; then
echo "WARNING: High rate limit usage!"
fi
fi
}
# Usage example
check_rate_limit "https://api.tourfold.com/api/v2/tours"
Caching Responses
#!/bin/bash
# Simple file-based caching
cache_dir="/tmp/tourfold_cache"
mkdir -p "$cache_dir"
get_cached_response() {
local url="$1"
local cache_file="$cache_dir/$(echo "$url" | md5sum | cut -d' ' -f1)"
# Check if cache exists and is less than 5 minutes old
if [ -f "$cache_file" ] && [ $(($(date +%s) - $(stat -c %Y "$cache_file"))) -lt 300 ]; then
echo "Using cached response for: $url"
cat "$cache_file"
else
echo "Fetching fresh data for: $url"
response=$(curl -s -H "Authorization: Bearer YOUR_TOKEN" "$url")
echo "$response" > "$cache_file"
echo "$response"
fi
}
# Usage example
get_cached_response "https://api.tourfold.com/api/v2/tours"
Rate Limit Strategies
1. Request Batching
Instead of making multiple individual requests, batch them when possible:
# Instead of multiple individual requests
for tour_id in tour_123 tour_456 tour_789; do
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.tourfold.com/api/v2/tours/$tour_id"
done
# Use batch endpoint
curl -X POST "https://api.tourfold.com/api/v2/tours/batch" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"tour_ids": ["tour_123", "tour_456", "tour_789"]
}'
2. Pagination Optimization
Use appropriate page sizes to reduce the number of requests:
# Use larger page sizes when possible
curl "https://api.tourfold.com/api/v2/tours?page=0&size=100" \
-H "Authorization: Bearer YOUR_TOKEN"
3. Webhook Integration
Use webhooks instead of polling for real-time updates:
# Instead of polling
while true; do
curl "https://api.tourfold.com/api/v2/tours?updated_since=$last_check" \
-H "Authorization: Bearer YOUR_TOKEN"
sleep 60
done
# Register a webhook endpoint
curl -X POST "https://api.tourfold.com/api/v2/webhook-endpoints" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"display_name": "Tour lifecycle listener",
"endpoint_url": "https://your-server.com/webhook",
"signature_scheme": "HMAC_SHA256",
"enabled": true,
"retry": true,
"subscriptions": ["device.updated", "user.updated"]
}'
Monitoring and Alerts
Setting Up Alerts
#!/bin/bash
# Simple rate limit monitoring script
monitor_rate_limits() {
local url="$1"
local log_file="/tmp/rate_limit_monitor.log"
# Get current usage
response=$(curl -s -I -H "Authorization: Bearer YOUR_TOKEN" "$url")
limit=$(echo "$response" | grep -i "x-ratelimit-limit" | cut -d' ' -f2 | tr -d '\r')
remaining=$(echo "$response" | grep -i "x-ratelimit-remaining" | cut -d' ' -f2 | tr -d '\r')
if [ -n "$limit" ] && [ -n "$remaining" ]; then
usage_percentage=$(( (limit - remaining) * 100 / limit ))
# Log usage
echo "$(date): Usage: ${usage_percentage}% (${remaining}/${limit})" >> "$log_file"
# Alert if usage is critical
if [ "$usage_percentage" -gt 90 ]; then
echo "CRITICAL: Rate limit usage at ${usage_percentage}%!" | tee -a "$log_file"
# Send alert (email, Slack, etc.)
fi
fi
}
# Monitor every 5 minutes
while true; do
monitor_rate_limits "https://api.tourfold.com/api/v2/tours"
sleep 300
done
Upgrading Your Rate Limits
Requesting Higher Limits
Contact our support team to request higher rate limits:
- Provide usage metrics: Show current usage patterns
- Explain use case: Describe your application's needs
- Demonstrate need: Show why higher limits are required
Enterprise Plans
Enterprise customers can get:
- Custom rate limits
- Dedicated infrastructure
- Priority support
- SLA guarantees
Common Mistakes to Avoid
❌ Don't Ignore Rate Limits
# Bad: No rate limit handling
curl "https://api.tourfold.com/api/v2/tours"
❌ Don't Retry Immediately
# Bad: Immediate retry
if [ $http_code -eq 429 ]; then
curl "https://api.tourfold.com/api/v2/tours" # This will fail again
fi
✅ Do Handle Rate Limits Properly
# Good: Proper rate limit handling
make_request() {
response=$(curl -s -w "%{http_code}" -o /tmp/response.json \
-H "Authorization: Bearer YOUR_TOKEN" \
"https://api.tourfold.com/api/v2/tours")
http_code="${response: -3}"
if [ "$http_code" -eq 429 ]; then
retry_after=$(curl -s -I "https://api.tourfold.com/api/v2/tours" | \
grep -i "retry-after" | cut -d' ' -f2 | tr -d '\r')
echo "Rate limited. Waiting $retry_after seconds..."
sleep "$retry_after"
make_request
else
cat /tmp/response.json
fi
}
Testing Rate Limits
Controlled Test Environment
Test retry handling locally or against a private non-production environment provided for your integration. Keep the API base URL configurable and do not load-test the production API.
Load Testing
#!/bin/bash
# Simple load test
load_test() {
local endpoint="$1"
local count="${2:-100}"
local rate_limited=0
echo "Testing $count requests to $endpoint..."
for ((i=1; i<=count; i++)); do
response=$(curl -s -w "%{http_code}" -o /dev/null \
-H "Authorization: Bearer YOUR_TOKEN" \
"$endpoint")
http_code="${response: -3}"
if [ "$http_code" -eq 429 ]; then
((rate_limited++))
fi
# Small delay to avoid overwhelming
sleep 0.1
done
echo "Rate limited requests: $rate_limited out of $count"
}
# Usage example
load_test "https://api.tourfold.com/api/v2/tours" 50
Next steps
- Learn about
Error handling - Understand
Pagination and filtering - Explore
Server-sent eventsfor real-time updates