> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pagination

> Cursor-based pagination scheme used by all list endpoints in the Qoder Cloud Agents API.

List endpoints in the Qoder Cloud Agents API use **cursor-based pagination**. Use the `next_page` value from a response as the `page` query parameter on the next request. Cursors remain stable even as data changes.

## Request parameters

| Parameter   | Type    | Required | Default | Description                                                   |
| ----------- | ------- | -------- | ------- | ------------------------------------------------------------- |
| `limit`     | integer | No       | 20      | Items per page, range 1–100                                   |
| `page`      | string  | No       | —       | Opaque cursor returned by the previous response's `next_page` |
| `before_id` | string  | No       | —       | Compatibility cursor: returns records before this ID          |
| `after_id`  | string  | No       | —       | Compatibility cursor: returns records after this ID           |

<Note>`page`, `before_id`, and `after_id` are mutually exclusive. Sending more than one cursor returns `400 invalid_request_error`.</Note>

## Response structure

All list endpoints return the same pagination envelope:

```json theme={null}
{
  "data": [
    { "id": "agent_abc123", "name": "my-agent", "...": "..." },
    { "id": "agent_def456", "name": "another-agent", "...": "..." }
  ],
  "next_page": "agent_def456",
  "first_id": "agent_abc123",
  "last_id": "agent_def456",
  "has_more": true
}
```

### Field descriptions

| Field       | Type           | Description                                                            |
| ----------- | -------------- | ---------------------------------------------------------------------- |
| `data`      | array          | Resources on the current page                                          |
| `next_page` | string \| null | Opaque cursor for the next page. Pass it as the `page` query parameter |
| `first_id`  | string \| null | ID of the first record on this page                                    |
| `last_id`   | string \| null | ID of the last record on this page                                     |
| `has_more`  | boolean        | Whether more records remain                                            |

## Basic usage

### Fetch the first page

```bash theme={null}
# Get the first 10 Agents
curl -s "https://api.qoder.com/api/v1/cloud/agents?limit=10" \
  -H "Authorization: Bearer $QODER_PAT"
```

### Fetch the next page

Use `next_page` from the previous response as `page`:

```bash theme={null}
# Get the next 10 Agents
curl -s "https://api.qoder.com/api/v1/cloud/agents?limit=10&page=agent_def456" \
  -H "Authorization: Bearer $QODER_PAT"
```

### Compatibility cursors

Some endpoints also accept `before_id` and `after_id` for ID-based cursor compatibility:

```bash theme={null}
# Get the 10 records after agent_def456
curl -s "https://api.qoder.com/api/v1/cloud/agents?limit=10&after_id=agent_def456" \
  -H "Authorization: Bearer $QODER_PAT"
```

## Full traversal example

The script below iterates through every Agent:

```bash theme={null}
#!/bin/bash
# Iterate over all Agents and print names
BASE_URL="https://api.qoder.com/api/v1/cloud"
next_page=""
page_num=1

while true; do
  url="$BASE_URL/agents?limit=50"
  if [ -n "$next_page" ]; then
    url="$url&page=$next_page"
  fi

  response=$(curl -s "$url" \
    -H "Authorization: Bearer $QODER_PAT")

  count=$(echo "$response" | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d['data']))")
  next_page=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin).get('next_page') or '')")

  echo "Page ${page_num}: ${count} records"

  echo "$response" | python3 -c "
import sys, json
data = json.load(sys.stdin)['data']
for item in data:
    print(f\"  - {item['id']}: {item.get('name', 'unnamed')}\")
"

  if [ -z "$next_page" ]; then
    break
  fi

  page_num=$((page_num + 1))
  sleep 0.1
done

echo "Done"
```

## `limit` behavior

| Value         | Behavior                                                                                     |
| ------------- | -------------------------------------------------------------------------------------------- |
| Omitted       | Defaults to 20                                                                               |
| 1             | Minimum, returns 1 record                                                                    |
| 100           | Maximum, returns 100 records                                                                 |
| 0 or negative | Returns 400 `invalid_request_error` with message `Field 'limit' must be a positive integer.` |
| > 100         | Returns 400 `invalid_request_error` with message `limit exceeds maximum of 100`              |

<Warning>
  Passing `limit > 100` returns 400. Use `limit=100` and `page` to page through larger result sets.
</Warning>

```bash theme={null}
# Fetch a single record to check whether data exists
curl -s "https://api.qoder.com/api/v1/cloud/agents?limit=1" \
  -H "Authorization: Bearer $QODER_PAT"
```

## Empty results

When there is no data or the end of the list has been reached:

```json theme={null}
{
  "data": [],
  "next_page": null,
  "first_id": null,
  "last_id": null,
  "has_more": false
}
```

## Notes

1. **Cursor stability** — `page` cursors are opaque and should be passed back exactly as returned.
2. **Sort order** — records are returned in descending creation time by default (newest first).
3. **Compatibility cursors** — `before_id` and `after_id` are retained for ID-based cursor compatibility.
4. **Concurrent paging** — paging is safe to perform concurrently from multiple clients.

## Next steps

<CardGroup cols={2}>
  <Card title="Overview" icon="rocket" href="/cloud-agents/overview">
    How Qoder Cloud Agents fits together.
  </Card>
</CardGroup>
