# Querying Lists

List endpoints use a shared query model for filtering, sorting, and pagination. Available filters
and sort fields are documented on each endpoint in the [API reference](/api). This page describes
the common client patterns.

## Filtering

Pass filter values as query parameters:

```bash title="Filter by query parameter"
curl "https://api.kordiam.app/api/v2/elements?groupIds=1,2&platformId=5" \
  -H "Authorization: Bearer ..."
```

List-valued filters accept comma-separated values (for example `groupIds=1,2,3`). The
[API reference](/api) is the source of truth for which filters accept multiple values on each
endpoint.

## Date Formats

Date parameters accept formats documented by each endpoint:

| Type       | Format                                      | Example                |
|------------|---------------------------------------------|------------------------|
| `datetime` | ISO 8601 instant or date-time with an offset | `2025-01-15T10:30:00+01:00` |
| `date`     | ISO 8601 date                               | `2025-01-15`           |

Range filters typically use inclusive boundaries. Verify the exact filter behavior in the
[API reference](/api) for each endpoint.

## Sorting

When an endpoint documents a `sort` query parameter, use the format `field,direction`, where
direction is `asc` or `desc`:

```bash title="Sort by field and direction"
curl "https://api.kordiam.app/api/v2/absences?sort=period.dateFrom,asc" \
  -H "Authorization: Bearer ..."
```

Requesting an unsupported sort field returns `400 Bad Request`. Sorting is endpoint-specific —
see each endpoint's documentation for whether `sort` is accepted and which fields are allowed.

## Pagination Modes

List endpoints expose pagination in one of two modes:

- **Hybrid** — both offset-based (`page` / `size`) and cursor-based (`cursor` / `size`)
  navigation are available, and the default response advertises both.
- **Cursor-only** — only `cursor` and `size` are part of the public contract; `page` metadata is
  never returned and exact totals are not available.

The [API reference](/api) indicates which mode each endpoint uses. Examples in this guide use
concrete endpoints purely to illustrate request and response shape.

## Default Pagination (Hybrid Endpoints)

When you call a hybrid list endpoint without pagination parameters, the API returns the first
page with both offset metadata and a cursor token. Use this initial response to choose your
pagination strategy.

```bash title="Default list request"
curl "https://api.kordiam.app/api/v2/users" \
  -H "Authorization: Bearer ..."
```

```json title="Response"
{
  "content": [],
  "size": 20,
  "hasMore": true,
  "nextCursor": "v1.Y3JlYXRpb25UaW1l...",
  "page": {
    "number": 0,
    "totalElements": 150,
    "totalPages": 8
  }
}
```

From here, continue with offset-based pagination using `page`, or switch to cursor-based
pagination using the returned `nextCursor`.

## Offset-Based Pagination

Use `page` and `size` query parameters for page-number navigation on hybrid endpoints:

```bash title="Page-number navigation"
curl "https://api.kordiam.app/api/v2/users?page=0&size=20" \
  -H "Authorization: Bearer ..."
```

When `page` is provided explicitly, `nextCursor` is omitted from the response.

| Parameter | Type      | Default | Description           |
|-----------|-----------|---------|-----------------------|
| `page`    | `integer` | `0`     | Page number, 0-based  |
| `size`    | `integer` | `20`    | Requested page size   |

Offset pagination is not available on cursor-only endpoints; check the [API reference](/api)
before relying on `page`.

## Cursor-Based Pagination

For large datasets, use cursor-based pagination for a stable forward-only window:

```bash title="Cursor navigation"
curl "https://api.kordiam.app/api/v2/elements?cursor=v1.Y3JlYXRpb25UaW1l&size=20" \
  -H "Authorization: Bearer ..."
```

```json title="Response"
{
  "content": [],
  "size": 20,
  "hasMore": true,
  "nextCursor": "v1.Y3JlYXRpb25UaW1l..."
}
```

<Mermaid chart={`flowchart TD
  A["Request first page"] --> B{"hasMore is true?"}
  B -- "No" --> C["Done"]
  B -- "Yes" --> D["Pass nextCursor back as cursor"]
  D --> B`} />

On hybrid endpoints, supplying `cursor` causes `page` metadata to be omitted from the response.
On cursor-only endpoints, `page` metadata is never returned regardless of input.

Rules:

- Treat `nextCursor` as an opaque string. Do not parse, construct, or modify it.
- Pass it back exactly as received in the `cursor` query parameter.
- `nextCursor` is only present when `hasMore` is `true`.
- Cursors are forward-only. There is no previous-page cursor.
- If the endpoint supports `sort`, the sort field and direction are encoded in the cursor.
  Changing `sort` while reusing a cursor returns `400 Bad Request`.
- On hybrid endpoints, `page` and `cursor` are mutually exclusive. Sending both in the same
  request returns `400 Bad Request`.

## Response Fields

Every list response includes these common fields:

| Field        | Type      | Always present                | Description                                                                                  |
|--------------|-----------|-------------------------------|----------------------------------------------------------------------------------------------|
| `content`    | `T[]`     | Yes                           | Array of result items                                                                        |
| `size`       | `int`     | Yes                           | Requested page or cursor window size                                                         |
| `hasMore`    | `boolean` | Yes                           | `true` when additional results exist beyond the current window, `false` on the last window   |
| `nextCursor` | `string`  | Default and cursor modes       | Opaque token for the next page. Present when `hasMore` is `true`, omitted otherwise          |
| `page`       | `object`  | Hybrid endpoints only          | Page metadata: `number` (0-based), `totalElements`, `totalPages`. Omitted on cursor-only     |

Mode summary:

| Field        | Hybrid default | Hybrid offset (`?page=N`) | Hybrid cursor (`?cursor=xxx`) | Cursor-only |
|--------------|----------------|---------------------------|-------------------------------|-------------|
| `hasMore`    | always         | always                    | always                        | always      |
| `nextCursor` | if `hasMore`   | omitted                   | if `hasMore`                  | if `hasMore`|
| `page`       | always         | always                    | omitted                       | never       |

## Combining Filters, Sorting, And Pagination

Filters narrow the dataset, sorting orders it, and pagination controls the window:

```bash
curl "https://api.kordiam.app/api/v2/elements?groupIds=5&size=50" \
  -H "Authorization: Bearer ..."
```

:::tip{title="Prefer cursors for large result sets"}

For large filtered result sets, prefer cursor-based pagination to avoid inconsistencies when data
changes between requests.

:::

## Limits

| Constraint        | Value |
|-------------------|-------|
| Default page size | 20    |
| Minimum page size | 1     |
| Maximum page size | 100   |

For endpoint-specific details, always defer to the [API reference](/api).
