---
title: Get Started
slug: devicepark/sdk-documentation/getting-started/get-started
description: Create a client, reserve a device, start a session and clean up.
docTags: 
createdAt: 2026-08-10T08:03:45.197Z
---

This guide builds the minimum complete Device Park workflow for a test runner: authenticate once, select capacity, reserve a device, create a managed session and return the device safely.

At the end, the runner will have handled these identifiers correctly:

| Identifier                 | Created by               | Used for                                        |
| -------------------------- | ------------------------ | ----------------------------------------------- |
| `serial` or `devicePoolId` | Device or pool selection | Allocation targeting                            |
| `allocationId`             | Create Allocation        | Session start, allocation status and release    |
| `sessionId`                | Start Session            | Session stop, Appium logs and screen recordings |

Read [How Device Park Works](docId\:NU6H7zhS-QaC9dYM1P-EL) first if allocation, Device Park session and Appium session are new concepts.

## Before You Begin

Make sure you have:

- installed the [Java, Node.js or .NET SDK](docId\:CGcNHeobHYgMIAJSgu6Ch)
- received `clientId` and `clientSecret` from your Device Park administrator
- access to at least one Device Park device or pool

Set the credentials:

```bash
export DEVICEPARK_CLIENT_ID=your-client-id
export DEVICEPARK_CLIENT_SECRET=your-client-secret
```

:::hint{type="info"}
Use the Java or TypeScript tab consistently as you move through the lifecycle. Both tabs perform the same Device Park operation.
:::

## Imports

:::CodeblockTabs
```java
import java.nio.file.Files;
import java.nio.file.Paths;

import io.testinium.devicepark.DeviceParkApiClient;
import io.testinium.devicepark.authentication.credentials.Credentials;
import io.testinium.devicepark.model.allocation.Allocation;
import io.testinium.devicepark.model.allocation.DeviceAllocationRequest;
import io.testinium.devicepark.model.common.PageDto;
import io.testinium.devicepark.model.devices.Device;
import io.testinium.devicepark.model.devices.ListDevicesRequest;
import io.testinium.devicepark.model.sessions.DeviceStartSessionRequest;
import io.testinium.devicepark.model.sessions.Session;
import io.testinium.devicepark.model.sessions.screenRecord.ScreenRecord;
import io.testinium.devicepark.model.sessions.screenRecord.ScreenRecordPaginationRequest;
```

```typescript
import { writeFile } from "node:fs/promises";
import {
  Credentials,
  DeviceAllocationRequestBuilder,
  DeviceParkApiClient,
  DeviceStartSessionRequestBuilder,
  ListDevicesRequestBuilder
} from "@device-park/public-sdk";
```

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

## Step 1: Create the Client

Create one client and reuse it for the complete flow.

:::CodeblockTabs
```java
DeviceParkApiClient client = DeviceParkApiClient.builder()
        .url("https://devicepark.testinium.io")
        .credentials(Credentials.of(
                System.getenv("DEVICEPARK_CLIENT_ID"),
                System.getenv("DEVICEPARK_CLIENT_SECRET")))
        .build();
```

```typescript
const client = DeviceParkApiClient.builder()
  .url("https://devicepark.testinium.io")
  .credentials(Credentials.fromEnvironment())
  .build();
```

```csharp
using var client = DeviceParkApiClient.Builder()
    .Url("https://devicepark.testinium.io")
    .Credentials(Credentials.FromEnvironment())
    .Build();
```
:::

The client obtains and renews access tokens automatically.

## Step 2: Select a Device

List devices and select a serial from the returned page.

Use a serial when the scenario requires one exact device. If any device from a managed group is acceptable, list pools and create the allocation with `devicePoolId` instead.

:::CodeblockTabs
```java
PageDto<Device> devices = client.devices().list(
        ListDevicesRequest.builder().page(0).size(20).build());

Device selectedDevice = devices.data().stream()
        .findFirst()
        .orElseThrow(() -> new IllegalStateException("No device is available"));
```

```typescript
const devices = await client.devices().list(
  new ListDevicesRequestBuilder().page(0).size(20).build()
);

const selectedDevice = devices.data[0];
if (!selectedDevice?.serial) {
  throw new Error("No device is available");
}
```

```csharp
var devices = await client.Devices.ListAsync(
    new ListDevicesRequest.Builder().Page(0).Size(20).Build());

var selectedSerial = devices.Data.FirstOrDefault()?.Serial
    ?? throw new InvalidOperationException("No device is available");
```
:::

If the test can use any device from a managed group, list pools and use `pool.id` instead of a serial.

## Step 3: Create an Allocation

Reserve the selected device.

:::CodeblockTabs
```java
Allocation allocation = client.allocations().create(
        DeviceAllocationRequest.builder()
                .serial(selectedDevice.serial())
                .priority(3)
                .build());

if (allocation.allocationId() == null) {
    throw new IllegalStateException("Allocation id is missing");
}
```

```typescript
const allocation = await client.allocations().create(
  new DeviceAllocationRequestBuilder()
    .serial(selectedDevice.serial)
    .priority(3)
    .build()
);

if (!allocation.allocationId) {
  throw new Error("Allocation id is missing");
}
```

```csharp
var allocation = await client.Allocations.CreateAsync(
    new DeviceAllocationRequest.Builder()
        .Serial(selectedSerial)
        .Priority(3)
        .Build());

var allocationId = allocation.AllocationId
    ?? throw new InvalidOperationException("Allocation id is missing");
```
:::

When `deviceSerial` is `null` or queue position is greater than zero, inspect the allocation until Device Park assigns a device. Reuse the existing `allocationId`; do not create duplicate allocations while waiting.

:::hint{type="warning"}
Do not create another allocation while waiting. Poll or inspect the same `allocationId` until a device is assigned or your test-runner deadline is reached.
:::

## Step 4: Start a Session

Start the session with the active allocation.

:::CodeblockTabs
```java
Session session = client.sessions().start(
        DeviceStartSessionRequest.builder()
                .allocationId(allocation.allocationId())
                .userId(42L)
                .userEmail("qa@example.com")
                .companyId(7L)
                .companyName("Example Company")
                .videoRecording(true)
                .build());
```

```typescript
const session = await client.sessions().start(
  new DeviceStartSessionRequestBuilder()
    .allocationId(allocation.allocationId)
    .userId(42)
    .userEmail("qa@example.com")
    .companyId(7)
    .companyName("Example Company")
    .videoRecording(true)
    .build()
);

if (!session.sessionId) {
  throw new Error("Session id is missing");
}
```

```csharp
var session = await client.Sessions.StartAsync(
    new DeviceStartSessionRequest.Builder()
        .AllocationId(allocationId)
        .UserId(42)
        .UserEmail("qa@example.com")
        .CompanyId(7)
        .CompanyName("Example Company")
        .VideoRecording(true)
        .Build());

var sessionId = session.SessionId
    ?? throw new InvalidOperationException("Session id is missing");
```
:::

Store `sessionId`. Use your Appium client to run automation commands for this session.

The SDK manages the Device Park session. Appium capability creation and automation commands remain in the Appium client or test framework.

## Step 5: Stop the Session

Stop the session after the test finishes:

:::CodeblockTabs
```java
client.sessions().stop(session.sessionId());
```

```typescript
await client.sessions().stop(session.sessionId);
```

```csharp
await client.Sessions.StopAsync(sessionId);
```
:::

Stopping the session does not release the allocation. You can start another session with the same active `allocationId`.

## Step 6: Collect Artifacts

Download the Appium log when it is needed for troubleshooting:

:::CodeblockTabs
```java
byte[] log = client.sessions().logs(session.sessionId());
Files.write(Paths.get("appium.log"), log);
```

```typescript
const log = await client.sessions().logs(session.sessionId);
await writeFile("appium.log", log);
```

```csharp
var log = await client.Sessions.LogsAsync(sessionId);
await File.WriteAllBytesAsync("appium.log", log);
```
:::

If recording was enabled, list screen records after the session has finalized:

:::CodeblockTabs
```java
PageDto<ScreenRecord> records = client.sessions().screenRecords(
        session.sessionId(),
        ScreenRecordPaginationRequest.builder().page(0).size(20).build());
System.out.println(records.data());
```

```typescript
const records = await client.sessions().screenRecords(session.sessionId);
console.log(records.data);
```

```csharp
var records = await client.Sessions.ScreenRecordsAsync(sessionId);
Console.WriteLine(records.Data.Count);
```
:::

## Step 7: Release the Allocation

Release the device after the final session:

:::CodeblockTabs
```java
client.allocations().delete(allocation.allocationId());
client.close();
```

```typescript
await client.allocations().delete(allocation.allocationId);
await client.close();
```

```csharp
await client.Allocations.DeleteAsync(allocationId);
// The using declaration disposes the client.
```
:::

Production test runners should stop sessions and release allocations from cleanup code so failed tests do not leave resources active.

The snippets above explain each business step separately. Use the complete examples for a self-contained program with imports, validation and cleanup:

- [Complete Node.js example](docId\:YncBWPNpB5fmS5CBlgGTj)
- [Complete Java example](docId\:Crq4nGNIdPa-TsqQPzbOq)

## Next Steps

- [Understand allocation targeting and queue behavior](docId\:sPz_N5rutGOmDKrBjbb0L)
- [Reuse an allocation for multiple sessions](docId\:ouSu3HjjBQLFsC2bURFU-)
- [Upload an APK or IPA](docId\:KyaNImcg1bsxfewffzLGc)
- [Handle pagination and filtering](docId\:dGs4iHB5eEr5U28AOL8T_)
- [Review exact SDK method signatures](docId\:OoaKfd3Ua6tGD-fnw_WuH)
- [Review response and request contracts](docId:-CQFsjSE5Bf_dV5p4FT7S)
