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

# Pagination

> How DevHelm API endpoints paginate results using offset, cursor, and slice patterns

The DevHelm API uses three pagination patterns depending on the endpoint. All paginated responses include metadata to navigate between pages.

## Offset pagination

Most list endpoints use offset pagination with `page` and `size` parameters.

### Request

| Parameter   | Type    | Description            | Default                           |
| ----------- | ------- | ---------------------- | --------------------------------- |
| `page`      | integer | Page number (0-based)  | `0`                               |
| `size`      | integer | Items per page (1–200) | `10` or `20` (varies by endpoint) |
| `sort`      | string  | Sort field             | varies                            |
| `sortOrder` | string  | `ASC` or `DESC`        | `ASC`                             |

```bash theme={null}
curl "https://api.devhelm.io/api/v1/monitors?page=0&size=20&sort=createdAt&sortOrder=DESC" \
  -H "Authorization: Bearer $DEVHELM_API_TOKEN"
```

### Response

Offset endpoints return one of two response shapes:

**With total count** (`PageResult`):

```json theme={null}
{
  "data": [...],
  "page": 0,
  "size": 20,
  "totalElements": 47,
  "totalPages": 3,
  "hasNext": true
}
```

**Without total count** (`TableValueResult`):

```json theme={null}
{
  "data": [...],
  "hasNext": true,
  "hasPrev": false
}
```

### Iterating through pages

```typescript theme={null}
let page = 0;
let hasNext = true;

while (hasNext) {
  const response = await fetch(
    `https://api.devhelm.io/api/v1/monitors?page=${page}&size=50`,
    { headers: { Authorization: `Bearer ${token}` } }
  );
  const result = await response.json();

  for (const monitor of result.data) {
    // Process each monitor
  }

  hasNext = result.hasNext;
  page++;
}
```

## Cursor pagination

Time-series and append-only data uses cursor pagination for consistent results.

### Request

| Parameter | Type    | Description                          | Default                  |
| --------- | ------- | ------------------------------------ | ------------------------ |
| `cursor`  | string  | Opaque cursor from previous response | *(start from beginning)* |
| `limit`   | integer | Items per page                       | `50` (varies: 1–200)     |

```bash theme={null}
curl "https://api.devhelm.io/api/v1/monitors/<id>/results?limit=50" \
  -H "Authorization: Bearer $DEVHELM_API_TOKEN"
```

### Response

```json theme={null}
{
  "data": [...],
  "nextCursor": "eyJpZCI6MTIzNH0=",
  "hasMore": true
}
```

### Iterating with cursors

```typescript theme={null}
let cursor: string | null = null;
let hasMore = true;

while (hasMore) {
  const url = new URL("https://api.devhelm.io/api/v1/monitors/<id>/results");
  url.searchParams.set("limit", "100");
  if (cursor) url.searchParams.set("cursor", cursor);

  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${token}` },
  });
  const result = await response.json();

  for (const check of result.data) {
    // Process each check result
  }

  cursor = result.nextCursor;
  hasMore = result.hasMore;
}
```

### Endpoints using cursor pagination

* Check results (`/api/v1/monitors/{id}/check-results`)
* Service catalog (`/api/v1/services`)
* Service poll results
* Webhook deliveries

## Single value responses

Some endpoints return a single item wrapped in a `data` field:

```json theme={null}
{
  "data": { "id": "...", "name": "..." }
}
```

## Sorting

For offset-paginated endpoints that accept `sort`, pass the field name. Common sortable fields:

* `createdAt` — creation timestamp (most common default)
* `name` — alphabetical
* `updatedAt` — last modified
* `status` — resource status

Spring-style multi-sort is supported on some endpoints: `sort=name,asc&sort=createdAt,desc`.
