---
title: Kotlin API reference
description: Configuration, functions, data models, and error types in OpenTester Android SDK 0.1.0.
---

# Kotlin API reference {#kotlin-api-reference}

Package: `dev.opentester.sdk`. This reference covers SDK `0.1.0`.

## OpenTesterConfig {#opentesterconfig}

```kotlin
data class OpenTesterConfig(
    val appId: String,
    val apiBaseUrl: String,
    val webBaseUrl: String,
    val redirectUri: String,
    val allowInsecureLocalhost: Boolean = false,
    val languageTag: String = "en",
)
```

| Field | Description |
| --- | --- |
| `appId` | App ID from the developer console; the server requires a UUID |
| `apiBaseUrl` | API origin, e.g. `https://api.opentester.app`; SDK appends `/api/v1` |
| `webBaseUrl` | Web origin; SDK appends `/sdk/authorize` for login |
| `redirectUri` | Registered HTTPS App Link; no query, fragment, or user information |
| `allowInsecureLocalhost` | Allow local development HTTP and sample callback; default `false` |
| `languageTag` | Language for SDK messages, API `Accept-Language`, and browser authentication; default `en` |

Origins must not contain paths, credentials, queries, or fragments. HTTPS is required by default. With `allowInsecureLocalhost = true`, HTTP is allowed only for `localhost`, `127.0.0.1`, `10.0.2.2`, and `[::1]`. Android cleartext policy must also be configured.

Only the `opentester-sample` custom scheme is allowed for development. Use verified HTTPS App Links for deployment. Invalid configuration throws during construction.

Supported SDK languages are English, Korean, Japanese, German, French, Hindi, Brazilian Portuguese, Turkish, and Indonesian (for example, `ko-KR`, `ja-JP`, `pt-BR`). Unsupported languages fall back to English. User-written reports are not translated.

## OpenTester {#opentester}

```kotlin
class OpenTester(val config: OpenTesterConfig)
```

Keep one instance across Activity recreation. Network functions use `Dispatchers.IO`, with a 10-second connection timeout and 15-second read timeout. HTTP redirects are not followed.

| Function | Returns | Behavior |
| --- | --- | --- |
| `authenticate(activity: Activity)` | `Unit` | Starts new authentication and opens a browser Custom Tab; call on the main thread |
| `createAuthenticationUri()` | `Uri` | Creates a new authentication URI for your own system-browser launcher |
| `suspend handleCallback(callback: Uri)` | `AccessGrant` | Validates the callback, exchanges the code, and stores the SDK session |
| `suspend checkAccess()` | `AccessGrant` | Checks current enrollment access on the server |
| `suspend submitBug(report: BugReport)` | `SubmittedIssue` | Submits a bug |
| `suspend submitFeedback(report: FeedbackReport)` | `SubmittedIssue` | Submits feedback |
| `logout()` | `Unit` | Clears the in-memory token and pending authentication |

`authenticate()` and `createAuthenticationUri()` reset the existing SDK session. `logout()` does not end the browser session. See [authentication](/sdk/authentication).

## AccessGrant and Tester {#accessgrant-and-tester}

```kotlin
data class Tester(
    val id: String,
    val name: String,
    val email: String,
)

data class AccessGrant(
    val appId: String,
    val campaignId: String,
    val user: Tester,
)
```

`AccessGrant` records approval at the moment of login or access checking. `campaignId` identifies the app's test campaign. Tokens remain in SDK memory and are not exposed in these models. Avoid unnecessary logging of tester details, including email.

## BugReport {#bugreport}

```kotlin
data class BugReport(
    val title: String,
    val description: String,
    val steps: String = "",
    val expected: String = "",
    val actual: String = "",
    val appVersion: String,
    val deviceInfo: String,
    val clientRequestId: String = UUID.randomUUID().toString(),
)
```

`appVersion` and `deviceInfo` have no constructor defaults. Use `""` when no device information is provided. `clientRequestId` is generated with `java.util.UUID`; retain it for retries.

## FeedbackReport {#feedbackreport}

```kotlin
data class FeedbackReport(
    val title: String,
    val description: String,
    val appVersion: String,
    val deviceInfo: String = "",
    val clientRequestId: String = UUID.randomUUID().toString(),
)
```

Feedback has no `steps`, `expected`, or `actual` arguments. See [input limits](/sdk/feedback#input-limits) for both models and deduplication behavior.

## SubmittedIssue {#submittedissue}

```kotlin
data class SubmittedIssue(
    val id: String,
    val title: String,
    val status: String,
)
```

New reports return `open`. A duplicate request can return the existing report's current status. Possible string values are `open`, `confirmed`, `fixed`, and `closed`.

## OpenTesterException {#opentesterexception}

All types below extend `OpenTesterException`:

| Type | Extra field | Meaning and recovery |
| --- | --- | --- |
| `NotAuthenticated` | None | Missing or expired SDK session; start login |
| `InvalidCallback` | None | Missing/expired login, mismatched callback or state; start a new login |
| `Api` | `statusCode: Int` | HTTP failure; check input for `400`, sign in for `401`, check enrollment for `403` |
| `Network` | Cause | Connection failure or timeout; retry reports with the same UUID |
| `InvalidResponse` | Cause | JSON or model parsing failed; check the server URL and versions |

Invalid configuration and empty titles/descriptions may throw validation exceptions outside this hierarchy. Handle host-app failures and coroutine cancellation separately.
