Documentation Index
Fetch the complete documentation index at: https://docs.hopx.ai/llms.txt
Use this file to discover all available pages before exploring further.
The HopX API implements rate limiting to ensure fair usage and system stability. Rate limits vary by endpoint and account plan.
Rate Limit Tiers
Default Limits
| Endpoint Type | Limit | Window |
|---|
| Control Plane API | 100 requests | per minute |
| VM Agent API | 300 requests | per minute |
| Template Builds | 10 builds | per hour |
| Sandbox Creation | 20 sandboxes | per minute |
Plan-Based Limits
Rate limits may vary based on your account plan:
- Free Tier - Default limits
- Pro Tier - 2x default limits
- Enterprise - Custom limits
Every API response includes rate limit headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1706400060
| Header | Description |
|---|
X-RateLimit-Limit | Maximum requests allowed in the window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the limit resets |
Rate Limit Exceeded
When you exceed the rate limit, you’ll receive a 429 Too Many Requests response:
{
"error": "Rate limit exceeded: 100 requests per minute",
"code": "RATE_LIMIT_EXCEEDED",
"request_id": "req_abc123",
"retry_after": 30
}
The retry_after field indicates how many seconds to wait before retrying.
Best Practices
import requests
response = requests.get(
"https://api.hopx.dev/v1/sandboxes",
headers={"Authorization": "Bearer $HOPX_API_KEY"}
)
remaining = int(response.headers.get('X-RateLimit-Remaining', 0))
limit = int(response.headers.get('X-RateLimit-Limit', 0))
print(f"Rate limit: {remaining}/{limit}")
if remaining < 10:
print("Warning: Approaching rate limit")
2. Implement Exponential Backoff
import time
import requests
def make_request_with_backoff(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code != 429:
return response
# Rate limited - wait and retry
retry_after = int(response.headers.get('Retry-After', 2 ** attempt))
print(f"Rate limited. Retrying after {retry_after}s")
time.sleep(retry_after)
raise Exception("Max retries exceeded")
3. Batch Operations
Instead of making many individual requests, batch operations when possible:
# Bad: One request per sandbox
for sandbox_id in sandbox_ids:
response = requests.get(
f"https://api.hopx.dev/v1/sandboxes/{sandbox_id}",
headers=headers
)
process(response.json())
# Good: One request for all sandboxes
response = requests.get(
"https://api.hopx.dev/v1/sandboxes",
headers=headers
)
sandboxes = response.json()["data"]
for sandbox in sandboxes:
process(sandbox)
4. Cache Responses
Cache responses that don’t change frequently:
import time
from functools import lru_cache
@lru_cache(maxsize=100)
def get_template(template_id, cache_time):
response = requests.get(
f"https://api.hopx.dev/v1/templates/{template_id}",
headers={"Authorization": "Bearer $HOPX_API_KEY"}
)
return response.json()
# Cache for 5 minutes
cache_key = int(time.time() // 300)
template = get_template("code-interpreter", cache_key)
5. Distribute Requests Over Time
import time
sandboxes_to_create = 50
rate_limit_per_minute = 20
delay = 60 / rate_limit_per_minute # 3 seconds
for i in range(sandboxes_to_create):
create_sandbox()
if i < sandboxes_to_create - 1:
time.sleep(delay)
Rate Limit Strategies
Sliding Window
Rate limits use a sliding window algorithm, not a fixed window. This means:
- Limits are enforced per 60-second rolling window
- Request counts decay as time passes
- Burst traffic is allowed up to the limit
Per-Endpoint Limits
Some endpoints have separate rate limits:
| Endpoint | Limit | Reason |
|---|
/v1/templates/build | 10/hour | Resource-intensive operation |
/v1/sandboxes (POST) | 20/minute | Prevent abuse |
/v1/sandboxes (GET) | 100/minute | Standard limit |
Handling Rate Limits in Production
Production-Ready Handler
import time
import requests
from typing import Optional
class RateLimitedClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.hopx.dev"
self.headers = {"Authorization": f"Bearer {api_key}"}
def request(self, method: str, path: str, **kwargs) -> requests.Response:
max_retries = 5
for attempt in range(max_retries):
response = requests.request(
method,
f"{self.base_url}{path}",
headers=self.headers,
**kwargs
)
# Success
if response.status_code < 400:
return response
# Rate limited
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 2 ** attempt))
print(f"Rate limited. Waiting {retry_after}s (attempt {attempt + 1}/{max_retries})")
time.sleep(retry_after)
continue
# Other errors - don't retry
response.raise_for_status()
raise Exception("Max retries exceeded due to rate limiting")
def get(self, path: str, **kwargs) -> requests.Response:
return self.request("GET", path, **kwargs)
def post(self, path: str, **kwargs) -> requests.Response:
return self.request("POST", path, **kwargs)
# Usage
client = RateLimitedClient("$HOPX_API_KEY")
response = client.get("/v1/sandboxes")
sandboxes = response.json()
Increasing Rate Limits
If you need higher rate limits:
- Upgrade Your Plan - Higher tiers include increased limits
- Contact Support - Request custom limits for your use case
- Optimize Your Code - Reduce unnecessary API calls
Monitoring Usage
Check your current usage via the API:
curl https://api.hopx.dev/v1/account/usage \
-H "Authorization: Bearer $HOPX_API_KEY"
Response:
{
"rate_limits": {
"control_plane": {
"limit": 100,
"remaining": 85,
"reset_at": "2025-01-28T00:01:00Z"
},
"vm_agent": {
"limit": 300,
"remaining": 250,
"reset_at": "2025-01-28T00:01:00Z"
}
}
}
Next Steps