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 uses cursor-based pagination for list endpoints. This provides consistent, efficient pagination even when data is being added or removed.
All list endpoints return a consistent structure:
{
"object": "list",
"data": [
{"id": "sandbox_1", ...},
{"id": "sandbox_2", ...}
],
"has_more": true,
"next_cursor": "cursor_abc123",
"url": "/v1/sandboxes",
"request_id": "req_abc123"
}
| Field | Type | Description |
|---|
object | string | Always “list” |
data | array | Array of resource objects |
has_more | boolean | Whether more results exist |
next_cursor | string | Cursor for next page (null if no more results) |
url | string | Endpoint URL |
request_id | string | Request ID |
cursor
Use the cursor query parameter to fetch the next page:
# First page
curl "https://api.hopx.dev/v1/sandboxes" \
-H "Authorization: Bearer $HOPX_API_KEY"
# Next page (using cursor from previous response)
curl "https://api.hopx.dev/v1/sandboxes?cursor=cursor_abc123" \
-H "Authorization: Bearer $HOPX_API_KEY"
limit
Control the number of results per page with the limit parameter:
curl "https://api.hopx.dev/v1/sandboxes?limit=50" \
-H "Authorization: Bearer $HOPX_API_KEY"
Default limits vary by endpoint:
- Sandboxes: 20 per page
- Templates: 50 per page
Maximum limit: 100 per page
Paginating Through Results
Example: Fetch All Sandboxes
import requests
def get_all_sandboxes(api_key):
url = "https://api.hopx.dev/v1/sandboxes"
headers = {"Authorization": f"Bearer {api_key}"}
all_sandboxes = []
cursor = None
while True:
params = {"limit": 100}
if cursor:
params["cursor"] = cursor
response = requests.get(url, headers=headers, params=params)
data = response.json()
all_sandboxes.extend(data["data"])
if not data["has_more"]:
break
cursor = data["next_cursor"]
return all_sandboxes
sandboxes = get_all_sandboxes("$HOPX_API_KEY")
print(f"Total sandboxes: {len(sandboxes)}")
Example: Fetch with Progress
def get_all_sandboxes_with_progress(api_key):
url = "https://api.hopx.dev/v1/sandboxes"
headers = {"Authorization": f"Bearer {api_key}"}
all_sandboxes = []
cursor = None
page = 1
while True:
params = {"limit": 50}
if cursor:
params["cursor"] = cursor
response = requests.get(url, headers=headers, params=params)
data = response.json()
page_sandboxes = data["data"]
all_sandboxes.extend(page_sandboxes)
print(f"Page {page}: Fetched {len(page_sandboxes)} sandboxes (total: {len(all_sandboxes)})")
if not data["has_more"]:
print("No more results")
break
cursor = data["next_cursor"]
page += 1
return all_sandboxes
Consistent Results
Cursor-based pagination provides consistent results even when data changes:
# Offset-based (bad) - can miss or duplicate items if data changes
response1 = get("/sandboxes?offset=0&limit=10")
# New sandbox created here
response2 = get("/sandboxes?offset=10&limit=10") # Might miss items!
# Cursor-based (good) - consistent results
response1 = get("/sandboxes?limit=10")
cursor = response1["next_cursor"]
# New sandbox created here
response2 = get(f"/sandboxes?cursor={cursor}&limit=10") # No duplicates or misses
Cursor-based pagination is more efficient for large datasets:
- O(1) lookups using the cursor
- No need to count or skip rows
- Works well with databases
Combine filters with pagination:
# List running sandboxes with pagination
curl "https://api.hopx.dev/v1/sandboxes?status=running&limit=50" \
-H "Authorization: Bearer $HOPX_API_KEY"
# Next page
curl "https://api.hopx.dev/v1/sandboxes?status=running&limit=50&cursor=cursor_abc123" \
-H "Authorization: Bearer $HOPX_API_KEY"
Example with filters:
def get_running_sandboxes(api_key):
url = "https://api.hopx.dev/v1/sandboxes"
headers = {"Authorization": f"Bearer {api_key}"}
running_sandboxes = []
cursor = None
while True:
params = {
"status": "running",
"limit": 50
}
if cursor:
params["cursor"] = cursor
response = requests.get(url, headers=headers, params=params)
data = response.json()
running_sandboxes.extend(data["data"])
if not data["has_more"]:
break
cursor = data["next_cursor"]
return running_sandboxes
All list endpoints support pagination:
| Endpoint | Default Limit | Max Limit |
|---|
GET /v1/sandboxes | 20 | 100 |
GET /v1/templates | 50 | 100 |
Best Practices
1. Use Reasonable Page Sizes
# Good: Fetch manageable chunks
response = get("/v1/sandboxes?limit=50")
# Bad: Fetching too many at once
response = get("/v1/sandboxes?limit=1000") # Over max limit (100)
2. Store and Reuse Cursors
# Save cursor for resuming later
last_cursor = None
for page in range(5):
params = {"limit": 20}
if last_cursor:
params["cursor"] = last_cursor
response = get("/v1/sandboxes", params=params)
data = response.json()
process_sandboxes(data["data"])
if not data["has_more"]:
break
last_cursor = data["next_cursor"]
# Resume later with last_cursor
3. Handle Empty Results
response = requests.get(url, headers=headers)
data = response.json()
if not data["data"]:
print("No results found")
elif not data["has_more"]:
print("This is the last page")
Shell Script Example
#!/bin/bash
API_KEY="$HOPX_API_KEY"
URL="https://api.hopx.dev/v1/sandboxes"
CURSOR=""
PAGE=1
while true; do
# Build URL with cursor if available
if [ -z "$CURSOR" ]; then
REQUEST_URL="$URL?limit=50"
else
REQUEST_URL="$URL?limit=50&cursor=$CURSOR"
fi
# Fetch page
RESPONSE=$(curl -s "$REQUEST_URL" -H "Authorization: Bearer $API_KEY")
# Extract data
COUNT=$(echo "$RESPONSE" | jq '.data | length')
HAS_MORE=$(echo "$RESPONSE" | jq -r '.has_more')
echo "Page $PAGE: $COUNT sandboxes"
# Check if more pages exist
if [ "$HAS_MORE" != "true" ]; then
echo "No more results"
break
fi
# Get next cursor
CURSOR=$(echo "$RESPONSE" | jq -r '.next_cursor')
PAGE=$((PAGE + 1))
done
Next Steps