---
title: Pagination and Filtering
slug: devicepark/sdk-documentation/reference/pagination-and-filtering
description: Configure list pagination, sorting and filtering.
docTags: 
createdAt: 2026-08-10T08:03:44.631Z
---

List methods return one page at a time. Use request builders to control page size, sorting and filters.

Every list-operation page contains its own filter constants, value types, examples and response model. This page documents only the behavior shared by all lists.

## Defaults

| Field       | Default | Description              |
| ----------- | ------- | ------------------------ |
| `page`      | `0`     | Zero-based page index    |
| `size`      | `20`    | Items requested per page |
| `sortBy`    | `ID`    | Sort field               |
| `direction` | `DESC`  | Sort direction           |

## Examples

:::CodeblockTabs
```typescript
const filterRequest: DeviceFilterRequest = {
  key: DeviceFilter.PLATFORM,
  value: "android",
  operation: SearchOperation.EQUAL
};

const request = new ListDevicesRequestBuilder()
  .page(0)
  .size(50)
  .sortBy("ID")
  .direction(SortDirection.DESC)
  .filters([filterRequest])
  .build();

const devices = await client.devices().list(request);
```

```java
DeviceFilterRequest filterRequest = DeviceFilterRequest.of(
        DeviceFilter.PLATFORM,
        "android",
        SearchOperation.EQUAL
);

ListDevicesRequest request = ListDevicesRequest.builder()
        .page(0)
        .size(50)
        .sortBy("ID")
        .direction(SortDirection.DESC)
        .filters(Collections.singletonList(filterRequest))
        .build();

PageDto<Device> devices = client.devices().list(request);
```

```csharp
var request = new ListDevicesRequest.Builder()
    .Page(0)
    .Size(50)
    .SortBy("ID")
    .Direction(SortDirection.DESC)
    .AddFilter(DeviceFilter.PLATFORM, "android", SearchOperation.EQUAL)
    .Build();

var devices = await client.Devices.ListAsync(request);
```
:::

The Java, Node.js and .NET SDKs transmit filters for device, pool, application, allocation, session and screen-record list requests. See the individual operation page for the exact constants and accepted values. Java resolves the account default pool with `pools().getDefaultPool()`. Node.js and .NET pool lists use `listByDefaultPool(...)`, which applies the default-pool filter automatically.

Java examples use `Collections.singletonList(filterRequest)` because the SDK targets Java 8. On Java 9 or newer, `List.of(filterRequest)` is equivalent. In .NET, `.Filters(...)` accepts any `IEnumerable<T>`, and `.AddFilter(...)` appends a single rule.

## How SDK Filters Are Sent

```typescript
const filterRequest: DeviceFilterRequest = {
  key: DeviceFilter.POOL_ID,
  value: "pool-123",
  operation: SearchOperation.EQUAL
};

const request = new ListDevicesRequestBuilder()
  .filters([filterRequest])
  .page(0)
  .size(10)
  .build();
```

The SDK maps that rule to indexed query values:

```text
filters[0].key=devicePools.id
filters[0].value=pool-123
filters[0].operation=EQUAL
sorting.page=0
sorting.size=10
sorting.sortBy=ID
sorting.direction=DESC
```

The .NET SDK sends the filter-key constant name (`POOL_ID`) and percent-encodes the square brackets (`filters%5B0%5D.key`).

Rules passed to `.filters(...)` keep their list order and are indexed as `filters[0]`, `filters[1]` and so on.

## Search Operations

| Operation      | Use                                          |
| -------------- | -------------------------------------------- |
| `EQUAL`        | Match the exact value                        |
| `NOT_EQUAL`    | Exclude the exact value                      |
| `GREATER_THAN` | Match values greater than the supplied value |
| `LESS_THAN`    | Match values less than the supplied value    |

## Operation-Specific Filters

| List operation                 | Filter details and response                                                                          |
| ------------------------------ | ---------------------------------------------------------------------------------------------------- |
| Devices                        | [Pool, serial, name, manufacturer, model, platform, OS, tag and state](docId\:T2lFRSsG2mhohPOA4K26-) |
| Device apps (Node.js and .NET) | [Bundle identifier, default status and file key](docId\:JOQ1A2pU5ih-Rqb7TDx_4)                       |
| Pools                          | [Pool name and default-pool status](docId\:fmKLq2CPwGu4aurSboUFg)                                    |
| Allocations                    | [Allocation id](docId\:GGobQpsUr2aKNz0jfCNYD)                                                        |
| Sessions                       | [Allocation, session, serial, state, user and company](docId\:yDnbFyoHkKjGUefb_-6rf)                 |
| Screen records                 | [Created timestamp](docId:9voFjQy3NQ7olg4uHLhTK)                                                     |
| Applications                   | [File key, file path, version and revision](docId\:SPDXnMADbDctpaPsO1gbH)                            |

## Page Result

Every list method returns `PageDto<T>` with `page`, `size`, `totalPages`, `totalElements` and `data`.

To read every item, increase the page index until the last page. Avoid requesting an unbounded page size.

## Read Every .NET Page

```csharp
var page = 0;

while (true)
{
    var result = await client.Devices.ListAsync(
        new ListDevicesRequest.Builder().Page(page).Size(100).Build());

    foreach (var device in result.Data)
    {
        Console.WriteLine(device.Serial);
    }

    if (result.IsLast)
    {
        break;
    }

    page++;
}
```

`PageDto<T>` exposes `IsLast` and `IsEmpty` in Java and .NET. In Node.js, compare `page` with `totalPages` yourself.

## Read Every Node.js Page

```typescript
let page = 0;

while (true) {
  const result = await client.devices().list(
    new ListDevicesRequestBuilder().page(page).size(100).build()
  );

  for (const device of result.data) {
    console.log(device.serial);
  }

  if (page >= result.totalPages - 1) {
    break;
  }

  page += 1;
}
```

Use a bounded page size to avoid large responses and request timeouts.

## Questions This Contract Answers

**Do I need to fetch every device and filter locally?**

Use supported filters directly in Java, Node.js or .NET. Device, pool, application, allocation, session and screen-record filters are sent server-side.

**Does List Pools include pool devices?**

No. It returns `PageDto<Pool>` with pool `id` and `name`. Use [List Devices](docId\:T2lFRSsG2mhohPOA4K26-) with `POOL_ID` where supported.

**What does an empty&#x20;**`data`**&#x20;array mean?**

The request succeeded but no visible record matched the page and filter criteria.
