> ## Documentation Index
> Fetch the complete documentation index at: https://docs.seam.co/llms.txt
> Use this file to discover all available pages before exploring further.

# SeamSDK

> This is the main entry point for the Seam Android SDK.

> Auto-generated from the Seam Android SDK Kotlin sources. Do not edit by hand — see `mintlify-codegen/android-reference/`.

## Overview

```kotlin theme={null}
class SeamSDK()
```

This is the main entry point for the Seam Android SDK.

Use the `getInstance` function to get the instance of this class.
You can only get the instance of the class after you have initialized the SDK by calling
`initialize`.

The `initialize` function will initialize the SDK.

## Thread Safety

* All StateFlow properties (`credentials`, `isActivated`, `unlockStatus`) are thread-safe
* All suspend functions can be called from any coroutine context
* `initialize` is thread-safe and idempotent

## StateFlow Lifecycle

* `credentials`: Emits whenever credential list changes, survives configuration changes
* `unlockStatus`: Emits unlock events, latest event is always available via .value
* `isActivated`: Reflects current SDK activation state

Collecting these flows is lifecycle-safe when used with Android lifecycle-aware scopes

## Offline Behavior

* SDK caches credentials and can work offline for unlock operations
* `activate` requires internet connection initially
* `refresh` requires internet connection
* `unlock` can work offline if credentials are already cached

## Error Recovery

* Most operations can be safely retried after fixing underlying issues
* Credential errors (in SeamCredential.errors) should be resolved before unlock
* Network errors during activate/refresh are transient and can be retried

## Background Processing

* Unlock operations continue in background
* StateFlow emissions work across app lifecycle

## Lifecycle

* Call `initialize` once per app session, typically in Application.onCreate()
* `activate` when user wants to use credential features
* No explicit cleanup needed - Android handles resource cleanup
* `deactivate` stops background operations but preserves credentials

***

## Companion object methods

### `initialize`

Initializes the Seam Android SDK. This should be called once at the
start of your application.

Example:

```kotlin theme={null}
try {
    SeamSDK.initialize(context, "seam_cst_...")
} catch (seamError: SeamError) {
    when (seamError) {
        is SeamError.AlreadyInitialized -> {
            // handle error when SDK is already initialized
        }
        is SeamError.DeactivationInProgress -> {
            // handle error when app is being deactivated
        }
        is SeamError.InternetConnectionRequired -> {
            // handle error when internet connection is required
        }
        is SeamError.InvalidClientSessionToken ->  {
            // handle error when client session token is invalid
        }
        else -> {
            // handle other errors
        }
    }
}
```

```kotlin theme={null}
suspend fun initialize(context: Context, clientSessionToken: String)
```

**Parameters**

| Parameter            | Description                                |
| -------------------- | ------------------------------------------ |
| `context`            | the Android context.                       |
| `clientSessionToken` | the client session token for the app user. |

**Throws**

* `SeamError.AlreadyInitialized` — if the SDK is already initialized.
* `SeamError.InternetConnectionRequired` — if no internet connection is available.
* `SeamError.InvalidClientSessionToken` — if the token format is invalid.
* `SeamError.DeactivationInProgress` — if a deactivation is in progress.

### `getInstance`

Returns the instance of `SeamSDK`. This can be used to get a handle to the
SeamSDK after it has been initialized.

This method is thread-safe and can be called from any thread.

```kotlin theme={null}
fun getInstance() : SeamSDK
```

**Returns** — The initialized SeamSDK instance.

**Throws**

* `SeamError.InitializationRequired` — if `initialize` has not been called yet.

***

## Properties

### `isActivated`

Returns whether the app user's phone has been activated.

This StateFlow emits `true` after successful `activate` call and `false` after `deactivate`.
The flow is thread-safe and can be collected from any coroutine context.
Latest value is always available via `.value` property.

```kotlin theme={null}
val isActivated
```

### `credentials`

Returns the list of `SeamCredential` for the current app user.

This StateFlow emits an immutable list whenever credentials change.
The list may be empty if no credentials are available or while loading.
Check each credential's `errors` property to determine if it's ready for use.

The flow is thread-safe and can be collected from any coroutine context.
Latest value is always available via `.value` property.

```kotlin theme={null}
// Observe credentials
seamSDK.credentials.collect { credentials ->
    // credentials is a list of [SeamCredential]
    if (credentials.isEmpty()) {
        // handle no credentials
    } else {
        // handle credentials (e.g. display them)
    }
}

// handle credential errors
SeamSDK.getInstance().credentials.collect { credentialsList ->
    val errors = credentialsList.flatMap { it.errors }
    errors.forEach { error ->
        when (error) {
            is SeamCredentialError.Expired -> { /* handle credential expiration error */ }
            is SeamCredentialError.Loading -> { /* handle not loaded yet */ }
            is SeamCredentialError.Unknown -> { /* handle unknown error */ }
            is SeamCredentialError.UserInteractionRequired -> {
                handleUserInteractionRequired(error.interaction)
            }
        }
    }
}

fun handleUserInteractionRequired(interaction: SeamRequiredUserInteraction) {
    when (interaction) {
         is SeamRequiredUserInteraction.CompleteOtpAuthorization -> { /* handle OTP authorization */ }
         is SeamRequiredUserInteraction.EnableBluetooth -> { /* handle Bluetooth error */ }
         is SeamRequiredUserInteraction.EnableInternet -> { /* handle Internet connection error*/ }
         is SeamRequiredUserInteraction.GrantPermissions -> { /* handle permissions error*/ }
    }
}
```

```kotlin theme={null}
val credentials
```

### `unlockStatus`

Returns the current status of the unlock feature.

This StateFlow emits `SeamUnlockEvent` instances as unlock operations progress.
Events include scanning, connection, access granted, errors, and timeout.
The flow retains the latest event, accessible via `.value` property.

Subscribe to this flow before calling `unlock` to ensure no events are missed.
The flow is thread-safe and can be collected from any coroutine context.

```kotlin theme={null}
val unlockStatus
```

***

## Methods

### `setUnlockEventListener`

Sets the listener for the unlock events.

```kotlin theme={null}
fun setUnlockEventListener(listener: (SeamUnlockEvent) -> Unit)
```

**Parameters**

| Parameter  | Description                               |
| ---------- | ----------------------------------------- |
| `listener` | the listener to listen for unlock events. |

### `setNotification`

Sets the notification for the unlock feature. Required for Assa Abloy foreground scanning.

```kotlin theme={null}
fun setNotification(notification: Notification)
```

**Parameters**

| Parameter      | Description                                     |
| -------------- | ----------------------------------------------- |
| `notification` | the notification to use for the unlock feature. |

### `setCredentialsListener`

Sets the listener for the credentials.

```kotlin theme={null}
fun setCredentialsListener(listener: (List<SeamCredential>) -> Unit)
```

**Parameters**

| Parameter  | Description                             |
| ---------- | --------------------------------------- |
| `listener` | the listener to listen for credentials. |

### `listCredentials`

Lists the credentials for the current app user.

```kotlin theme={null}
fun listCredentials() : List<SeamCredential>
```

**Returns** — a SeamResult of a list of AcsPhoneCredential. If the SDK has not been initialized yet, the result will be a SeamFailure with `SeamError.InitializationRequired`.

### `unlock`

Unlocks the app user's phone.

Initiates an unlock operation for the specified credential. Progress events are emitted
to `unlockStatus` StateFlow. The operation continues even if the app goes to background.

Works offline if credentials are already cached. Requires the device to have the
necessary hardware (Bluetooth, NFC, etc.) and permissions granted.

```kotlin theme={null}
val seamSDK = SeamSDK.getInstance()
// Start collecting unlock events before unlock
coroutineScope.launch {
    seamSDK.unlockStatus.collect { event ->
        when (event) {
            is SeamUnlockEvent.ScanningStarted -> { /* handle scanning started */ }
            is SeamUnlockEvent.Connecting -> { /* handle connecting */ }
            is SeamUnlockEvent.AccessGranted -> { /* handle access granted */ }
            is SeamUnlockEvent.Timeout -> { /* handle timeout */ }
            is SeamUnlockEvent.ReaderError -> { /* handle reader error */ }
            else -> { /* handle other events */ }
        }
    }
}

// Perform unlock
try {
    val credentialId = credential.id
    // Timeout is optional
    seamSDK.unlock(
        credentialId = credentialId,
        unlockProximity = UnlockProximity.TOUCH,
        timeout = 30.seconds
    )
} catch (seamError: SeamError) {
    when (seamError) {
        is SeamError.ActivationRequired -> {
            // handle error when SDK is not activated
        }
        is SeamError.CredentialErrors -> {
            val credentialErrors = seamError.errors
            handleCredentialErrors(credentialErrors)
            // handle error when there are credential errors
        }
        is SeamError.InitializationRequired -> {
            // handle error when SDK is not initialized
        }
        is SeamError.IntegrationNotFound -> {
            // handle error when integration is not found, Such as Assa Abloy, Latch and Salto
        }
        is SeamError.InvalidCredentialId -> {
            // handle error when credential ID is invalid
        }
        else -> {
            // handle other errors
        }
    }
}

// Handle credential errors on unlock
fun handleCredentialErrors(credentialErrors: List<SeamCredentialError>) {
    credentialErrors.forEach { credentialError ->
        when (credentialError) {
            is SeamCredentialError.Invalid -> {
                // handle error when credential is invalid
            }

            is SeamCredentialError.Expired -> {
                // handle error when credential is expired
            }

            is SeamCredentialError.Loading -> {
                // handle error when credential is not loaded yet
            }

            is SeamCredentialError.UserInteractionRequired -> {
                // handle user interaction required credential error
            }
            is SeamCredentialError.InvalidUnlockProximity -> {
                // handle invalid unlock proximity credential error
            }
            is SeamCredentialError.Unknown -> {
                // handle unknown credential error
            }
        }
    }
}
```

```kotlin theme={null}
fun unlock(credentialId: CredentialId, unlockProximity: UnlockProximity? = null, timeout: Duration? = null) : Job
```

**Parameters**

| Parameter         | Description                                                                                                                                                                                                                    |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `credentialId`    | the credential ID to unlock. CredentialId is a type alias for String.                                                                                                                                                          |
| `timeout`         | the timeout for the unlock operation. If null, uses provider default.                                                                                                                                                          |
| `unlockProximity` | the unlock proximity `UnlockProximity`. If null, uses provider default, which is the first in the list of `SeamCredential.supportedUnlockProximities`. The `SeamCredential` must have at least one supported unlock proximity. |

**Returns** — a Job that can be used to cancel the unlock operation.

**Throws**

* `SeamError.InitializationRequired` — if the SDK has not been initialized yet.
* `SeamError.IntegrationNotFound` — if the integration is not found.
* `SeamError.InvalidCredentialId` — if the credential ID is invalid.
* `SeamError.ActivationRequired` — if the app user's phone has not been activated yet.
* `SeamError.CredentialErrors` — if the credential has unresolved errors.
* `SeamError.InvalidUnlockProximity` — if the unlock proximity is invalid.

### `suspend activate`

Activates the app user's phone.

Prepares the SDK for use by syncing with the server and setting up background services.
This operation requires an active internet connection on first activation.
Safe to call multiple times - subsequent calls are no-ops if already activated.

After successful activation, `isActivated` will emit `true` and credentials will
start syncing automatically.

```kotlin theme={null}
val seamSDK = SeamSDK.getInstance()
try {
    // activate is a suspend function
    seamSDK.activate()
} catch (seamError: SeamError) {
    when (seamError) {
        is SeamError.InitializationRequired -> {
            // handle error when SDK is already initialized
        }
        is SeamError.InternetConnectionRequired -> {
            // handle error when internet connection is required
        }
        is SeamError.InvalidClientSessionToken ->  {
            // handle error when client session token is invalid
        }
        else -> {
            // handle other errors
        }
    }
}
```

```kotlin theme={null}
suspend fun activate()
```

**Throws**

* `SeamError.InitializationRequired` — if the SDK has not been initialized yet.
* `SeamError.InternetConnectionRequired` — if no internet connection is available.
* `SeamError.InvalidClientSessionToken` — if the client session token is invalid.

### `suspend deactivate`

Deactivates the app user's phone.

Stops background operations and cleans up resources. Credentials remain cached
and available for the next activation. After deactivation, `isActivated` will emit `false`.

This method is safe to call multiple times and will not throw if already deactivated.

```kotlin theme={null}
val seamSDK = SeamSDK.getInstance()
try {
    // deactivate is a suspend function
    seamSDK.deactivate(deintegrate = true)
} catch (seamError: SeamError) {
    when (seamError) {
        is SeamError.InitializationRequired -> {
            // handle error when SDK is not initialized
        }
        is SeamError.DeactivationInProgress -> {
            // handle error when internet connection is required
        }
        else -> {
            // handle other errors
        }
    }
}
```

```kotlin theme={null}
suspend fun deactivate(deintegrate: Boolean = false)
```

**Parameters**

| Parameter     | Description                                               |
| ------------- | --------------------------------------------------------- |
| `deintegrate` | If true, removes device association and clears all state. |

**Throws**

* `SeamError.InitializationRequired` — if the SDK has not been initialized yet.
* `SeamError.DeactivationInProgress` — if a deactivation is already in progress.

### `suspend refresh`

Refreshes the credentials for the current app user.

Manually triggers a sync with the server to fetch latest credentials.
This operation requires an active internet connection. You should call
`initialize` and `activate` first.

The `credentials` StateFlow will be updated before this method returns.
In most cases, automatic background sync makes manual refresh unnecessary.

```kotlin theme={null}
val seamSDK = SeamSDK.getInstance()
try {
    seamSDK.refresh()
} catch (seamError: SeamError) {
    when (seamError) {
        is SeamError.InitializationRequired -> {
            // handle error when SDK is not initialized
        }
        is SeamError.DeactivationInProgress -> {
            // handle error when app is being deactivated
        }
        else -> {
            // handle other errors
        }
    }
}
```

```kotlin theme={null}
suspend fun refresh() : List<SeamCredential>
```

**Returns** — The updated list of credentials after refresh completes.

**Throws**

* `SeamError.InitializationRequired` — if the SDK has not been initialized yet.
* `SeamError.DeactivationInProgress` — if a deactivation is in progress.
