Rate limiting
The Sitepaste API implements rate limiting to ensure fair usage and platform stability. This guide explains the limits, how to monitor them, and best practices for staying within limits.
Rate limit tiers
Different API endpoints have different rate limits based on their resource cost:
| Operation Type | Limit | Window | Applies To |
|---|---|---|---|
| Write Operations | 60 requests | 1 minute | Creating/updating pages |
| Heavy Operations | 20 requests | 1 hour | Triggering builds |
| IP Baseline | 120 requests | 1 minute | All public API endpoints |
Write operations
Endpoints:
POST /api/v1/public/pages
Limit: 60 requests per minute per business account
Scope: Shared across all your API tokens
This allows for reasonable bulk operations while preventing abuse.
Heavy operations
Endpoints:
POST /api/v1/public/builds
Limit: 20 requests per hour per business account
Scope: Shared across all your API tokens
Builds are expensive operations that regenerate your entire site. The hourly limit prevents resource exhaustion.
IP baseline
Limit: 120 requests per minute per IP address
Scope: All public API requests from the same IP
This is a protective baseline to prevent abuse from any single source.
Rate limit headers
Every API response includes rate limit information in the headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
When you exceed the limit, you’ll also see:
Retry-After: 60
Header descriptions
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
Retry-After | Seconds to wait before retrying (only on 429 errors) |
Monitoring rate limits
Check headers in response
curl -i -X POST https://sitepaste.com/api/v1/public/pages \
-H "Authorization: Bearer sp_your_token_here" \
-H "Content-Type: application/json" \
-d '{"title": "Test", "content": "Hello"}'
Response headers:
HTTP/2 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
Content-Type: application/json
{"id":"...","slug":"test",...}
Track usage in your application
#!/bin/bash
# Example: Parse rate limit headers
response=$(curl -i -X POST https://sitepaste.com/api/v1/public/pages \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"title": "Test", "content": "Hello"}')
remaining=$(echo "$response" | grep -i "X-RateLimit-Remaining" | cut -d' ' -f2)
echo "Remaining requests: $remaining"
if [ "$remaining" -lt 5 ]; then
echo "Warning: Approaching rate limit!"
fi
Rate limit exceeded
When you exceed a rate limit, you’ll receive a 429 Too Many Requests response:
Status: 429 Too Many Requests
Headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Retry-After: 60
Body:
{
"error": "rate limit exceeded",
"message": "too many requests, please try again later"
}
What to do
- Stop making requests immediately - You’re already rate limited
- Wait for the duration in
Retry-After- Usually 60 seconds (1 minute) or 3600 seconds (1 hour) - Implement exponential backoff - Don’t retry immediately when the window resets
- Review your usage pattern - Optimize to stay within limits
Best practices
1. Batch operations
Don’t do this:
# Creates 50 pages with 50 requests
for i in {1..50}; do
curl -X POST /api/v1/public/pages \
-H "Authorization: Bearer $TOKEN" \
-d "{\"title\": \"Post $i\", \"content\": \"Content\"}"
# Triggers 50 builds!
curl -X POST /api/v1/public/builds \
-H "Authorization: Bearer $TOKEN"
done
Do this instead:
# Creates 50 pages with 50 requests
for i in {1..50}; do
curl -X POST /api/v1/public/pages \
-H "Authorization: Bearer $TOKEN" \
-d "{\"title\": \"Post $i\", \"content\": \"Content\"}"
done
# Triggers ONE build at the end
curl -X POST /api/v1/public/builds \
-H "Authorization: Bearer $TOKEN"
2. Implement rate limit awareness
import requests
import time
API_BASE = "https://sitepaste.com/api/v1"
TOKEN = "sp_your_token_here"
def create_page(data):
response = requests.post(
f"{API_BASE}/public/pages",
headers={"Authorization": f"Bearer {TOKEN}"},
json=data
)
# Check rate limit
remaining = int(response.headers.get("X-RateLimit-Remaining", 0))
if remaining < 5:
print(f"Warning: Only {remaining} requests remaining")
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
return create_page(data) # Retry
return response.json()
# Create multiple pages with awareness
pages = [
{"title": "Page 1", "content": "Content 1"},
{"title": "Page 2", "content": "Content 2"},
# ... more pages
]
for page in pages:
result = create_page(page)
print(f"Created: {result['slug']}")
3. Add delays between requests
If you’re making many requests, add small delays to stay well within limits:
# 60 requests per minute = 1 request per second
for i in {1..50}; do
curl -X POST /api/v1/public/pages \
-H "Authorization: Bearer $TOKEN" \
-d "{\"title\": \"Post $i\", \"content\": \"Content\"}"
sleep 1 # Wait 1 second between requests
done
4. Use exponential backoff
When you hit a rate limit, implement exponential backoff:
import time
import random
def make_request_with_backoff(func, max_retries=5):
for attempt in range(max_retries):
try:
response = func()
if response.status_code == 429:
if attempt == max_retries - 1:
raise Exception("Max retries exceeded")
# Exponential backoff with jitter
wait = (2 ** attempt) + random.uniform(0, 1)
print(f"Rate limited. Waiting {wait:.2f} seconds...")
time.sleep(wait)
continue
return response
except Exception as e:
if attempt == max_retries - 1:
raise
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
raise Exception("Failed after all retries")
5. Coordinate multiple tokens
If you’re using multiple API tokens for different integrations, remember:
- Rate limits are per business account, not per token
- Multiple tokens share the same rate limit pool
- Coordinate your integrations to avoid conflicts
Rate limit windows
Sliding windows
Rate limits use sliding windows, not fixed time intervals:
Example (60 requests per minute):
- 12:00:00 - Make 60 requests (allowed)
- 12:00:30 - Make 1 request (rejected - still 60 requests in the last 60 seconds)
- 12:01:01 - Make 1 request (allowed - only 1 request in the last 60 seconds)
This is more flexible than fixed windows and prevents burst abuse.
Build rate limit (hourly)
The 20 builds per hour limit works the same way:
- Not reset at the top of every hour
- Tracks the last 60 minutes of build requests
- Resets gradually as old requests age out
Development mode
In development environments:
- Rate limiting is disabled
- Headers still appear but limits are not enforced
- Use this to test your integration without restrictions
Production: Rate limits are strictly enforced
Troubleshooting
I’m getting rate limited but I’m not making many requests
Possible causes:
- Multiple tokens - Remember, limits are per business account, not per token
- Multiple sources - Check if you have multiple scripts/integrations running
- Dashboard usage - Manual dashboard operations don’t count, but dashboard API calls do
Can I request higher rate limits?
Currently, rate limits are fixed for all Pro plan users. If you have a legitimate use case requiring higher limits:
- Optimize your usage pattern first (batching, delays, etc.)
- Contact support with your use case details
- Enterprise plans with custom limits may be available in the future
What counts as a request?
- Counts: All successful requests (200, 201, 202, etc.)
- Counts: Failed requests (400, 404, etc.)
- Counts: Unauthorized requests (401, 403)
- Counts: Rate limited requests (429)
- Doesn’t count: Requests that fail before authentication (500 errors, network issues)
Summary
- Write operations: 60 per minute
- Build operations: 20 per hour
- Monitor headers:
X-RateLimit-Remaining - Respect
Retry-Afterwhen rate limited - Batch operations to stay within limits
- Implement backoff for robustness
By following these guidelines, you’ll build reliable integrations that work within the API’s rate limits.