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

# Kotlin SDK - API Reference

> All public methods with signatures for the Kotlin SDK.

All public API is in the `dev.westyx.nexus` package.

## Factory

### `NexusClient.create`

```kotlin theme={null}
suspend fun create(
    config: NexusConfig,
    engine: HttpClientEngine? = null,
): NexusClient
```

Creates a new `NexusClient` and performs an initial synchronous sync before returning. Throws `NexusInitException` wrapping any underlying failure if the initial sync does not succeed. The `engine` parameter is optional and is intended for testing with `MockEngine`.

## Config / secret / flag getters

All getters call `ensureFresh()` internally, which triggers a background sync if the snapshot is older than `config.ttl`. They never block on the network call - the stale value is returned immediately while sync runs in the background.

### `getString`

```kotlin theme={null}
fun getString(key: String, default: String): String
```

Returns the string value for `key` from the config snapshot, or `default` if the key is not present or the value is empty.

### `getBoolean`

```kotlin theme={null}
fun getBoolean(key: String, default: Boolean): Boolean
```

Returns the boolean value for `key`. Parses `"true"` / `"false"` (case-insensitive strict). Returns `default` if the key is missing or the value cannot be parsed.

### `getInt`

```kotlin theme={null}
fun getInt(key: String, default: Int): Int
```

Returns the integer value for `key`. Returns `default` if the key is missing or the value is not a valid integer.

### `getDouble`

```kotlin theme={null}
fun getDouble(key: String, default: Double): Double
```

Returns the double value for `key`. Returns `default` if the key is missing or the value is not a valid double.

### `getJson`

```kotlin theme={null}
fun getJson(key: String): JsonElement?
```

Returns the raw `JsonElement` value stored in the snapshot for `key`, or `null` if not found. Use when the value type is not known at compile time.

### `getFlag`

```kotlin theme={null}
fun getFlag(key: String, default: Boolean = false): Boolean
```

Returns `true` if the feature flag `key` is active, `false` if it is inactive, or `default` if the key is not found in the flags snapshot.

### `getSecret`

```kotlin theme={null}
fun getSecret(key: String): String
```

Returns the plaintext value of secret `key` from the in-memory snapshot.

**Throws:**

* `NexusPublicKeyException` - when the client was created with a `wxp_...` key
* `NexusServiceKindMismatchException` - when the service is of kind `frontend`
* `NexusSecretNotFoundException` - when `key` is not present in the secrets snapshot

### `getSecretFilePath`

```kotlin theme={null}
fun getSecretFilePath(key: String): String
```

Returns the absolute path to a temporary file containing the value of secret `key`. Only available for secrets of type `file`. The file is created during sync and deleted when `close()` is called.

**Throws:**

* `NexusPublicKeyException` - when the client was created with a `wxp_...` key
* `NexusSecretNotFoundException` - when `key` is not a known file-type secret

## Write API *(v0.5.0)*

The write API allows programmatic secret creation and deletion. **Available for secret keys only**. Using a public key throws `NexusPublicKeyException` immediately, before the network call.

### `setSecret`

```kotlin theme={null}
suspend fun setSecret(key: String, value: String, type: String = "text")
```

Creates or updates a secret with the given key, plaintext value, and optional type (defaults to `"text"`).

```kotlin theme={null}
try {
    client.setSecret("stripe_secret_key", "sk_test_1234...")
} catch (e: NexusRateLimitedException) {
    logger.error("Rate limit hit on setSecret - retry after ${e.retryAfter}")
}
```

**Throws:**

* `NexusPublicKeyException` - when the client uses a `wxp_...` key
* `NexusRateLimitedException` - HTTP 429 on write endpoint
* `NexusUnauthorizedException` - HTTP 401
* `NexusBillingException` - HTTP 402 (billing overdue)
* `NexusException` - any other error

### `deleteSecret`

```kotlin theme={null}
suspend fun deleteSecret(key: String)
```

Deletes a secret and all its versions.

```kotlin theme={null}
try {
    client.deleteSecret("old_api_key")
} catch (e: NexusRateLimitedException) {
    logger.error("Rate limit hit on deleteSecret - retry after ${e.retryAfter}")
}
```

**Throws:**

* `NexusPublicKeyException` - when the client uses a `wxp_...` key
* `NexusRateLimitedException` - HTTP 429 on write endpoint
* `NexusUnauthorizedException` - HTTP 401
* `NexusBillingException` - HTTP 402 (billing overdue)
* `NexusException` - any other error

### `deleteSecretVersion`

```kotlin theme={null}
suspend fun deleteSecretVersion(key: String, version: Int)
```

Deletes a specific version of a secret.

```kotlin theme={null}
try {
    client.deleteSecretVersion("stripe_secret_key", 3)
} catch (e: NexusRateLimitedException) {
    logger.error("Rate limit hit on deleteSecretVersion - retry after ${e.retryAfter}")
}
```

**Throws:**

* `NexusPublicKeyException` - when the client uses a `wxp_...` key
* `NexusRateLimitedException` - HTTP 429 on write endpoint
* `NexusUnauthorizedException` - HTTP 401
* `NexusBillingException` - HTTP 402 (billing overdue)
* `NexusException` - any other error

## A/B evaluation

### `evaluateAB`

```kotlin theme={null}
suspend fun evaluateAB(
    keys:       List<String>,
    userId:     String,
    attributes: Map<String, String> = emptyMap(),
): Map<String, Boolean>
```

Sends a server-side A/B evaluation request to `POST /v1/flags/evaluate-ab`. Returns a map of flag key to `true`/`false` for the given `userId` and optional `attributes`.

```kotlin theme={null}
val results = client.evaluateAB(
    keys       = listOf("checkout-v2", "banner-v3"),
    userId     = "user-42",
    attributes = mapOf("country" to "HU", "plan" to "pro"),
)
if (results["checkout-v2"] == true) {
    showNewCheckout()
}
```

**Throws:**

* `NexusAbAddonNotAvailableException` - when the A/B testing add-on is not active for this project (HTTP 403)
* `NexusException` - for any other non-success HTTP status

## Sync

### `sync`

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

Manually triggers a full sync against `GET /v1/sync`. Uses ETag/If-None-Match to skip the response body when nothing has changed (304 Not Modified). Updates the in-memory snapshot atomically on success.

**Throws:**

* `NexusUnauthorizedException` - HTTP 401
* `NexusBillingException` - HTTP 402 (also sets billing-overdue flag and calls `observer.onBillingOverdue()`)
* `NexusNotFoundException` - HTTP 404
* `NexusQuarantinedException` - HTTP 429 with quarantine body

## Stream

### `connectStream`

```kotlin theme={null}
fun connectStream()
```

Starts the SSE stream connection in a background coroutine. Config changes and flag toggles published on the Nexus platform trigger a `sync()` call automatically. The stream reconnects with exponential back-off on transient failures.

### `disconnectStream`

```kotlin theme={null}
fun disconnectStream()
```

Cancels all active stream coroutines and sets `streamStatus` to `DISCONNECTED`. Does not affect the background TTL sync or the HTTP client.

### `streamStatus`

```kotlin theme={null}
val streamStatus: StateFlow<StreamStatus>
```

A `StateFlow` that reflects the current stream connection state. Possible values:

| Value          | Meaning                                                                                    |
| -------------- | ------------------------------------------------------------------------------------------ |
| `CONNECTED`    | SSE connection is established and receiving events                                         |
| `FALLBACK`     | Stream gave up after `MAX_STREAM_ERRORS` (3) consecutive failures; TTL sync remains active |
| `DISCONNECTED` | Not connected; either never started, or temporarily between reconnect attempts             |

## Lifecycle

### `close`

```kotlin theme={null}
fun close()
```

Cancels the internal coroutine scope, closes both HTTP clients, and deletes all temp files written by `getSecretFilePath`. Call this when the application shuts down. After `close()`, the client is unusable.
