> ## 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.

# .NET SDK - API Reference

> Every public method and property on NexusClient in the .NET SDK.

Every public method and property on `NexusClient`. All read methods are non-blocking - they hit the in-memory cache. Only `CreateAsync()` and `SyncAsync()` make network calls.

## Construction

### `NexusClient.CreateAsync(NexusConfig, CancellationToken = default)`

Creates a client and runs a **blocking** initial sync. The returned `Task<NexusClient>` resolves only after the first sync completes.

```csharp theme={null}
await using var client = await NexusClient.CreateAsync(new NexusConfig
{
    BaseUrl = "...",
    ApiKey  = "...",
});
```

| Throws               | When                                                            |
| -------------------- | --------------------------------------------------------------- |
| `NexusInitException` | Initial sync failed - `InnerException` has the underlying cause |
| `ArgumentException`  | `BaseUrl` or `ApiKey` missing or invalid                        |

## Configs

### `(JsonElement? value, bool found) GetConfig(string key)`

Returns the resolved config value as a `JsonElement` (the wire-level JSON node), and a `found` boolean.

```csharp theme={null}
var (value, found) = client.GetConfig("database.url");
if (found)
    Console.WriteLine(value!.Value.GetString());
```

The value is whatever JSON shape the server stored - string, number, boolean, array, or object.

### `IReadOnlyDictionary<string, JsonElement> GetAllConfigs()`

Snapshot copy of every config key-value pair currently in the cache.

public-key clients see only `is_public: true` entries.

## Feature flags

### `bool GetFlag(string key, bool defaultValue = false)`

Returns the `is_active` state of a flag, or `defaultValue` when the key is absent.

```csharp theme={null}
bool isOn = client.GetFlag("checkout.v2");                  // false if missing
bool isOn = client.GetFlag("checkout.v2", defaultValue: true);
```

### `IReadOnlyDictionary<string, bool> GetAllFlags()`

Snapshot copy of every flag key-is\_active pair in the cache.

## AB Testing

### `Task<IReadOnlyDictionary<string, bool>> EvaluateABAsync(IEnumerable<string> keys, string userId, IDictionary<string, object>? attributes, CancellationToken = default)`

Evaluates one or more feature flags against the AB Testing add-on. Unlike `GetFlag`, this method always makes a network call.

```csharp theme={null}
var results = await client.EvaluateABAsync(
    keys: new[] { "checkout.v2", "homepage.banner" },
    userId: "user-42",
    attributes: new Dictionary<string, object>
    {
        ["country"] = "DE",
        ["plan"]    = "pro",
    });

bool checkoutV2 = results["checkout.v2"];
```

`attributes` may be `null` - it is serialised as an empty object.

| Throws                              | When                                                                          |
| ----------------------------------- | ----------------------------------------------------------------------------- |
| `NexusAbAddonNotAvailableException` | Server returned HTTP 403 - the AB Testing add-on is not active for the tenant |
| `NexusUnauthorizedException`        | Server returned HTTP 401                                                      |
| `NexusBillingException`             | Server returned HTTP 402 - tenant has overdue invoices                        |
| `NexusNotFoundException`            | Server returned HTTP 404                                                      |
| `ArgumentNullException`             | `keys` is `null`                                                              |

## Secrets (secret key only)

### `Task<string> GetSecretAsync(string key)`

Returns the plaintext value of a secret.

```csharp theme={null}
string dbPass = await client.GetSecretAsync("DB_PASSWORD");
```

| Throws                         | When                         |
| ------------------------------ | ---------------------------- |
| `NexusPublicKeyException`      | The client uses a public key |
| `NexusSecretNotFoundException` | The key is not in the cache  |

### `string? GetSecretFilePath(string key)`

Returns the absolute filesystem path of a materialised `file`-type secret, or `null` when the key is unknown or refers to a `text`-type secret. Always non-blocking.

```csharp theme={null}
string? certPath = client.GetSecretFilePath("tls.cert");
if (certPath is not null)
    using var cert = X509Certificate2.CreateFromPemFile(certPath);
```

`file`-type secrets are written automatically to `Path.GetTempPath()` during every sync, with the naming convention `nexus-<key>-<hash>`. The hash is derived from the secret value (SHA-256, first 16 hex chars) so the path **changes whenever the value changes**. Files for secrets that disappear from a sync are deleted on disk. All remaining temp files are cleaned up by `Dispose()` / `DisposeAsync()`.

## Secrets - Write API *(v0.5.0)* (secret key only)

### `Task SetSecretAsync(string key, string value, CancellationToken = default)`

Creates or updates a secret with the given key and value.

```csharp theme={null}
await client.SetSecretAsync("DB_PASSWORD", "new-password");
await client.SetSecretAsync("TLS_CERT", certPem);
```

| Throws                              | When                                                              |
| ----------------------------------- | ----------------------------------------------------------------- |
| `NexusPublicKeyException`           | The client uses a public key                                      |
| `NexusRateLimitedException`         | Server returned HTTP 429 - rate limit exceeded on write endpoints |
| `NexusUnauthorizedException`        | Server returned HTTP 401                                          |
| `NexusServiceKindMismatchException` | The service `kind` is `"frontend"`                                |

### `Task DeleteSecretAsync(string key, CancellationToken = default)`

Deletes a secret by key.

```csharp theme={null}
await client.DeleteSecretAsync("DEPRECATED_API_KEY");
```

| Throws                              | When                                                              |
| ----------------------------------- | ----------------------------------------------------------------- |
| `NexusPublicKeyException`           | The client uses a public key                                      |
| `NexusRateLimitedException`         | Server returned HTTP 429 - rate limit exceeded on write endpoints |
| `NexusUnauthorizedException`        | Server returned HTTP 401                                          |
| `NexusServiceKindMismatchException` | The service `kind` is `"frontend"`                                |

### `Task DeleteSecretVersionAsync(string key, int version, CancellationToken = default)` *(v0.5.0)*

Deletes a specific version of a secret.

```csharp theme={null}
await client.DeleteSecretVersionAsync("DB_PASSWORD", version: 3);
```

| Throws                              | When                                                              |
| ----------------------------------- | ----------------------------------------------------------------- |
| `NexusPublicKeyException`           | The client uses a public key                                      |
| `NexusRateLimitedException`         | Server returned HTTP 429 - rate limit exceeded on write endpoints |
| `NexusUnauthorizedException`        | Server returned HTTP 401                                          |
| `NexusServiceKindMismatchException` | The service `kind` is `"frontend"`                                |

## Disposing the client

Always dispose the client via `Dispose()` / `DisposeAsync()` (or `await using`) on shutdown. Disposal:

* Cancels the SSE background task (if `ConnectStream()` was ever called).
* Deletes every temp file written for `file`-type secrets.
* Releases the internally-managed `HttpClient` instances.

```csharp theme={null}
await using var client = await NexusClient.CreateAsync(config);
// ... application work ...
// On scope exit: stream stops, temp files removed, HttpClient disposed.
```

## Metadata

| Property            | Type             | Description                                                 |
| ------------------- | ---------------- | ----------------------------------------------------------- |
| `KeyType`           | `string`         | `"sk"` or `"pk"` - derived from the configured `ApiKey`     |
| `SyncedAt`          | `DateTimeOffset` | Timestamp of the last successful sync                       |
| `IsStreamConnected` | `bool`           | `true` while the SSE stream is connected and pushing events |

## Sync / lifecycle

### `Task SyncAsync(CancellationToken = default)`

Forces a sync now, bypassing the TTL. Atomically replaces the cache. ETag / `If-None-Match` is used automatically; a 304 resets the TTL without downloading data. Rarely needed.

### `void ConnectStream()`

Starts the SSE live-update background task. Idempotent - calling more than once is a no-op. See [SSE live updates](sse-live-updates).

### `void DisconnectStream()`

Stops the SSE task. Safe to call multiple times.

### `Dispose()` / `DisposeAsync()`

Stops the SSE background task, deletes any `file`-type secret temp files, and releases the internally-managed `HttpClient`. Always call (or use `await using`) before the application exits.
