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

# Pagination

> Paginating HopX API list results using cursor-based pagination. Navigate through large result sets efficiently using cursor-based pagination. Learn how to use pagination parameters, handle page boundaries, and iterate through all results. Essential for listing sandboxes, templates, and other resources. Includes pagination examples and best practices.

The HopX API uses cursor-based pagination for list endpoints. This provides consistent, efficient pagination even when data is being added or removed.

## List Response Format

All list endpoints return a consistent structure:

```json theme={null}
{
  "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                                     |

## Pagination Parameters

### cursor

Use the `cursor` query parameter to fetch the next page:

```bash theme={null}
# 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:

```bash theme={null}
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

```python theme={null}
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

```python theme={null}
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
```

## Cursor-Based Pagination Benefits

### Consistent Results

Cursor-based pagination provides consistent results even when data changes:

```python theme={null}
# 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
```

### Performance

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

## Filtering with Pagination

Combine filters with pagination:

```bash theme={null}
# 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:

```python theme={null}
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
```

## Endpoints with Pagination

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

```python theme={null}
# 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

```python theme={null}
# 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

```python theme={null}
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

```bash theme={null}
#!/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
```

## Related

* **[API Introduction](/api/introduction)** - Learn about the HopX API
* **[Rate Limits](/api/concepts/rate-limits)** - Understand API rate limits
* **[Data Model](/api/concepts/data-model)** - Learn about API resources
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK (handles pagination automatically)
* [CLI Reference](/cli/introduction) - Command-line interface

## Next Steps

* **[Data Model](/api/concepts/data-model)** - Core resources and data structures
* **[Rate Limits](/api/concepts/rate-limits)** - Request rate limits
* **[Errors](/api/concepts/errors)** - Error handling and codes
