---
title: List Pools
slug: devicepark/sdk-documentation/pools/list-pools
description: List and filter managed device pools available for allocation.
docTags: 
createdAt: 2026-08-10T08:03:44.631Z
---

A pool is a managed group of devices. Use a pool when the test can run on any suitable device from that group and availability matters more than one exact serial.

:::hint{type="info"}
`List Pools` returns pool identifiers, names and whether each pool is the default pool. It does not return the devices inside each pool.
:::

To retrieve devices from a pool, use [List Devices](docId\:T2lFRSsG2mhohPOA4K26-) with `DeviceFilter.POOL_ID`. To reserve any suitable device from the pool, pass `pool.id` as `devicePoolId` to [Create Allocation](docId\:sPz_N5rutGOmDKrBjbb0L).

## SDK Method

| Java                              | Node.js                                            | .NET                                                  | Returns         |
| --------------------------------- | -------------------------------------------------- | ----------------------------------------------------- | --------------- |
| `client.pools().list(request)`    | `await client.pools().list(request?)`              | `await client.Pools.ListAsync(request?)`              | `PageDto<Pool>` |
| Not available                     | `await client.pools().listByDefaultPool(request?)` | `await client.Pools.ListByDefaultPoolAsync(request?)` | `PageDto<Pool>` |
| `client.pools().getDefaultPool()` | Not available                                      | `await client.Pools.GetDefaultPoolAsync()`            | `Pool`          |

`client.pools()` returns a shared `PoolsApi` instance. Node.js and .NET allow the list request to be omitted. Java accepts `null` for `list(...)`, but `ListPoolsRequest.builder().build()` makes the selected defaults explicit.

Java `getDefaultPool()` and .NET `GetDefaultPoolAsync()` return a single `Pool`. Java throws `IllegalStateException` when no default pool exists.

## Understanding `isDefault`

`isDefault` is read-only metadata returned by Device Park for each pool. It tells the caller whether the pool is marked as a default pool in Device Park; it does not change the pool configuration.

| Value   | Meaning                                               |
| ------- | ----------------------------------------------------- |
| `true`  | The pool is marked as a default pool                  |
| `false` | The pool is a regular, non-default pool               |
| `null`  | The response did not provide default-pool information |

The wire field and SDK property are named `isDefault`:

| Context       | Access              |
| ------------- | ------------------- |
| JSON response | `"isDefault": true` |
| Java          | `pool.isDefault()`  |
| Node.js       | `pool.isDefault`    |

There is no `isDefaultPool` property in the Java or Node.js SDK.

Pool listing uses this information as follows:

- `list(...)` lists pools visible to the caller. Its results can contain default and non-default pools.
- Node.js and .NET `listByDefaultPool(...)` send an `IS_DEFAULT = true` filter and return only pools marked as default.
- Java `getDefaultPool()` sends the same filter and returns the first matching pool.

:::hint{type="warning"}
`isDefault: true` does not mean that a device is currently available in the pool, and it does not automatically select the pool for allocation. To allocate from that pool, explicitly pass its `id` as `devicePoolId`.
:::

## Required Imports

:::CodeblockTabs
```java
import java.util.Collections;

import io.testinium.devicepark.model.common.PageDto;
import io.testinium.devicepark.model.common.SearchOperation;
import io.testinium.devicepark.model.common.SortDirection;
import io.testinium.devicepark.model.pools.ListPoolsRequest;
import io.testinium.devicepark.model.pools.Pool;
import io.testinium.devicepark.model.pools.PoolFilter;
import io.testinium.devicepark.model.pools.PoolFilterRequest;
```

```typescript
import {
  ListPoolsRequestBuilder,
  PoolFilter,
  SearchOperation,
  SortDirection,
  type PageDto,
  type Pool,
  type PoolFilterRequest
} from "@device-park/public-sdk";
```

```csharp
using Testinium.DevicePark;
using Testinium.DevicePark.Models;
```
:::

## Request Fields

`ListPoolsRequest` contains two top-level fields:

| Field     | Type                                              | Default           | Description                          |
| --------- | ------------------------------------------------- | ----------------- | ------------------------------------ |
| `filters` | `PoolFilterRequest[]` / `List<PoolFilterRequest>` | Empty             | Pool filter rules                    |
| `sorting` | `Sorting`                                         | Default `Sorting` | Pagination and sorting configuration |

The builder exposes every field through these methods:

| Builder method                      | Value type                             | Default | Description                       |
| ----------------------------------- | -------------------------------------- | ------- | --------------------------------- |
| `.page(value)`                      | integer                                | `0`     | Zero-based page index             |
| `.size(value)`                      | integer                                | `20`    | Maximum pools requested           |
| `.sortBy(value)`                    | string                                 | `ID`    | Server-side sort field            |
| `.direction(value)`                 | `SortDirection`                        | `DESC`  | `ASC` or `DESC`                   |
| `.addFilter(key, value, operation)` | `PoolFilter`, value, `SearchOperation` | None    | Appends one filter                |
| `.filters(rules)`                   | Pool filter list                       | Empty   | Replaces the complete filter list |
| `.build()`                          | None                                   | —       | Returns the completed request     |

Java additionally exposes `getFilters()`, `setFilters(...)`, `getSorting()` and `setSorting(...)` on `ListPoolsRequest`. The Java getter returns an unmodifiable filter list, while the setter copies the supplied list.

## Available Pool Filters

| Constant                | Query key    | Value type | Supported operations                              | Purpose                            |
| ----------------------- | ------------ | ---------- | ------------------------------------------------- | ---------------------------------- |
| `PoolFilter.NAME`       | `NAME`       | string     | `EQUAL`, `NOT_EQUAL`, `GREATER_THAN`, `LESS_THAN` | Compare the pool name              |
| `PoolFilter.IS_DEFAULT` | `IS_DEFAULT` | boolean    | `EQUAL`                                           | Match default or non-default pools |

Each filter is a `PoolFilterRequest` with the following fields:

| Field       | Java type         | Node.js type            | Required |
| ----------- | ----------------- | ----------------------- | -------- |
| `key`       | `PoolFilter`      | `PoolFilter` value      | Yes      |
| `value`     | `Object`          | `unknown`               | Yes      |
| `operation` | `SearchOperation` | `SearchOperation` value | Yes      |

Java can create one rule with `PoolFilterRequest.of(key, value, operation)`. It also exposes getters and setters for all three fields. Node.js represents the same contract as a typed object.

The Java and Node.js SDKs send pool filters supplied to `list(...)`. Node.js and .NET also expose `listByDefaultPool(...)`, which applies the `IS_DEFAULT = true` rule automatically. Java `getDefaultPool()` applies that same rule and returns one `Pool`.

## Request Mapping

The list operation has no request body. OAuth authorization is managed by the SDK client; callers do not supply headers to `list(...)`.

All three SDKs send:

```text
sorting.page=0
sorting.size=20
sorting.sortBy=ID
sorting.direction=DESC
```

All three SDKs send each filter as indexed query data:

```text
filters[0].key=NAME
filters[0].value=Android Regression
filters[0].operation=EQUAL
```

## List Pools

:::CodeblockTabs
```java
PageDto<Pool> pools = client.pools().list(
        ListPoolsRequest.builder()
                .page(0)
                .size(20)
                .sortBy("ID")
                .direction(SortDirection.DESC)
                .build()
);

pools.data().forEach(pool ->
        System.out.println(
                pool.id() + " - " + pool.name() + " - isDefault: " + pool.isDefault()
        ));
```

```typescript
import {
  ListPoolsRequestBuilder,
  SortDirection
} from "@device-park/public-sdk";

const pools = await client.pools().list(
  new ListPoolsRequestBuilder()
    .page(0)
    .size(20)
    .sortBy("ID")
    .direction(SortDirection.DESC)
    .build()
);

for (const pool of pools.data) {
  console.log(`${pool.id} - ${pool.name} - isDefault: ${pool.isDefault}`);
}
```

```csharp
var pools = await client.Pools.ListAsync(new ListPoolsRequest.Builder()
    .Page(0)
    .Size(20)
    .SortBy("ID")
    .Direction(SortDirection.DESC)
    .Build());

foreach (var pool in pools.Data)
{
    Console.WriteLine($"{pool.Id} - {pool.Name} - isDefault: {pool.IsDefault}");
}
```
:::

## Filter Pools by Name

Node.js sends this filter to Device Park:

```typescript
const filterRequest: PoolFilterRequest = {
  key: PoolFilter.NAME,
  value: "Android Regression",
  operation: SearchOperation.EQUAL
};

const pools = await client.pools().list(
  new ListPoolsRequestBuilder()
    .filters([filterRequest])
    .page(0)
    .size(20)
    .build()
);
```

```csharp
var pools = await client.Pools.ListAsync(new ListPoolsRequest.Builder()
    .AddFilter(PoolFilter.NAME, "Android Regression", SearchOperation.EQUAL)
    .Page(0)
    .Size(20)
    .Build());
```

The equivalent Java request is:

```java
PoolFilterRequest nameFilter = PoolFilterRequest.of(
        PoolFilter.NAME,
        "Android Regression",
        SearchOperation.EQUAL
);

ListPoolsRequest request = ListPoolsRequest.builder()
        .filters(Collections.singletonList(nameFilter))
        .page(0)
        .size(20)
        .build();
```

## List the Default Pool

Node.js `listByDefaultPool(...)` and .NET `ListByDefaultPoolAsync(...)` preserve the request pagination and sorting values and apply `IS_DEFAULT = true`. Java `getDefaultPool()` applies the same filter and returns the first matching `Pool`.

:::CodeblockTabs
```java
Pool defaultPool = client.pools().getDefaultPool();

System.out.println(defaultPool.id() + " - isDefault: " + defaultPool.isDefault());
```

```typescript
const defaultPools = await client.pools().listByDefaultPool(
  new ListPoolsRequestBuilder()
    .page(0)
    .size(20)
    .build()
);

for (const pool of defaultPools.data) {
  console.log(`${pool.id} - isDefault: ${pool.isDefault}`);
}
```

```csharp
var defaultPools = await client.Pools.ListByDefaultPoolAsync(
    new ListPoolsRequest.Builder().Page(0).Size(20).Build());

foreach (var pool in defaultPools.Data)
{
    Console.WriteLine($"{pool.Id} - isDefault: {pool.IsDefault}");
}

// When a single pool is enough:
var defaultPool = await client.Pools.GetDefaultPoolAsync();
```
:::

## Response Model

The method returns `PageDto<Pool>`.

### Page Fields

| Field           | Java type    | Node.js type | Meaning                   |
| --------------- | ------------ | ------------ | ------------------------- |
| `size`          | `int`        | `number`     | Requested page size       |
| `page`          | `int`        | `number`     | Zero-based returned page  |
| `totalPages`    | `int`        | `number`     | Total number of pages     |
| `totalElements` | `long`       | `number`     | Total matching pool count |
| `data`          | `List<Pool>` | `Pool[]`     | Pools in the current page |

Java exposes `size()`, `page()`, `totalPages()`, `totalElements()`, `data()`, `isLast()` and `isEmpty()` on `PageDto<Pool>`.

### Pool Fields

| Field       | Type    | Nullable | Meaning                                                                |
| ----------- | ------- | -------- | ---------------------------------------------------------------------- |
| `id`        | string  | Yes      | Identifier used as allocation `devicePoolId`                           |
| `name`      | string  | Yes      | Customer-facing pool name                                              |
| `isDefault` | boolean | Yes      | Read-only status showing whether Device Park marks the pool as default |

```json
{
  "size": 20,
  "page": 0,
  "totalPages": 1,
  "totalElements": 1,
  "data": [
    {
      "id": "android-regression",
      "name": "Android Regression",
      "isDefault": true
    }
  ]
}
```

No device list is nested inside a `Pool`. Use the pool id in allocation when Device Park should choose an available member.

## Empty Result

An empty `data` array is a successful response. It means the current credentials cannot see a pool on that page or no pool matched the transmitted filter. It does not mean the SDK failed.

## Next Steps

- [Create, delete or change pool devices](docId\:ObX8hTXvKifuvFe9uTuit)
- [Review all pool request and response types](docId:6rgeXT-fvPXowF0_lRTJj)
- [List devices from one pool](docId\:T2lFRSsG2mhohPOA4K26-)
- [Create a pool-based allocation](docId\:sPz_N5rutGOmDKrBjbb0L)
