Skip to content
Console

.NET SDK

Use the .NET SDK when your client runs on .NET or inside Unity.

The NuGet package name is Thalovant.Sdk. It multi-targets net8.0 and netstandard2.1, which covers Unity 2021 and newer. The net8.0 build has zero external dependencies; the netstandard2.1 target only depends on the System.Text.Json package.

Source and releases: thalovant-dotnet-sdk on GitHub.

Terminal window
dotnet add package Thalovant.Sdk

This flow signs in, creates a client identity, and sends one request over WSS.

using Thalovant;
var api = new ThalovantControlPlane();
await api.LoginAsync("[email protected]", "password");
var result = await api.CreateClientIdentityAsync(
"hub-id",
new CreateClientIdentityOptions("dotnet-demo-client"));
using var client = new ThalovantClient(result.Identity);
await client.ConnectAsync();
var reply = await client.AskAsync("Tell me a short clean joke.");
Console.WriteLine(reply.Text);
await client.CloseAsync();

new ThalovantControlPlane() uses https://api.thalovant.com by default.

Accounts with multi-factor authentication enabled must include a TOTP code or a one-time recovery code with the login. Without one, the API rejects the sign-in with HTTP 401 and code mfa_required, surfaced as ThalovantApiException.ErrorCode.

await api.LoginAsync("[email protected]", "password", otpCode: "123456");
// Or use a one-time recovery code instead:
await api.LoginAsync("[email protected]", "password", recoveryCode: "abcd-efgh-ijkl");

The otpCode and recoveryCode values are sent only when provided.

Device login asks your browser to approve the sign-in, so services and apps never handle your password. The SDK prints a short code and the address https://dash.thalovant.com/activate, opens that page when it can, and waits while you approve the request in the dashboard with your normal sign-in, including Google sign-in or MFA. On approval the SDK holds a scoped, revocable API token, returned as a typed DeviceLoginResult.

Device login needs SDK 0.1.1 or newer. Approving the request needs a paid workspace plan; a free plan gets HTTP 402.

var result = await api.LoginWithBrowserAsync(new DeviceLoginOptions
{
Scopes = new[] { "hubs:read", "clients:write" },
ClientName = "my-tool",
});
Console.WriteLine($"{result.TokenId} expires {result.ExpiresAt}");

Manage the resulting token on the dashboard’s API Tokens page.

Pass a stored API token when the process should start authenticated, such as CI jobs and services. Mint one on the API Tokens page or with LoginWithBrowserAsync; the page shows scopes, expiry, and last use, and can revoke the token at any time.

var api = new ThalovantControlPlane(accessToken: Environment.GetEnvironmentVariable("THALOVANT_API_TOKEN"));

ThalovantClient connects to the hub over WSS only in this release. Constructing it with HubProtocol.Https or HubProtocol.Mqtt throws ThalovantUnsupportedProtocolException. Endpoint selection still prefers wss, then https, then mqtt, so identities created for multi-protocol hubs keep working.

Use the Python, Node.js, Go, or Rust SDK when the client needs the HTTPS or MQTT data plane today.

Identities can be built from JSON or loaded from a JSON file. On Linux and macOS the file must not be group- or world-readable; run chmod 600 <path> first. The permission check is skipped on Windows and on the netstandard2.1 Unity build.

var identity = ThalovantIdentity.FromFile("/path/to/identity.json");
using var client = new ThalovantClient(identity);

The identity document uses the same snake_case fields the API returns, including access_key, password, crypto_key, site_id, and the optional data_plane_endpoints, protocols, and mqtt sections.

Mutating control-plane commands return durable operations. Poll them with the typed helper:

var operation = await api.GetOperationAsync("operation-id");
Console.WriteLine(operation.Status); // Requested, Committed, Applied, Ready, Failed, TimedOut

See Operations for lifecycle and retry guidance.

var subscription = client.On("speak", e => Console.WriteLine(e.DisplayText));
// Later, when the listener is no longer needed:
subscription.Close();

AskAsync

Send one request and receive a normalized reply.

On

Observe hub bus events by name with a closeable subscription.

GetOperationAsync

Poll a durable control-plane command with a typed status.

ListPublicHubsAsync

Discover public hubs before sign-in.

For cross-language recipes, see SDK Functions.

Since SDK 0.1.5 the control plane can create hubs, runtime groups, and skill installs. Browsing the catalog with ListMarketplaceSkillsAsync() needs hubs:read and works on any plan. CreateHubAsync, CreateRuntimeGroupAsync, InstallRuntimeGroupSkillAsync, ReleaseHubAsync, and ReleaseRuntimeGroupAsync need hubs:write and a paid plan.

var group = await api.CreateRuntimeGroupAsync(new CreateRuntimeGroupOptions("kiosks"));
var hub = await api.CreateHubAsync(new CreateHubOptions("joke-garden", new JsonObject())
{
RuntimeGroupId = (string)group["id"]!,
});
hub = await api.GetHubAsync((string)hub["id"]!);
await api.UpdateHubAsync((string)hub["id"]!, new UpdateHubOptions { Active = false }, (string)hub["etag"]!);

UpdateHubAsync and DeleteHubAsync take the hub’s current etag as a required argument. See Provision Hubs for the full flow, the immutable fields, and the error table.

Symptom Check
ThalovantApiException with Missing Thalovant API access token Call api.LoginAsync(...) or api.LoginWithBrowserAsync(...) before private API actions, or pass accessToken: to ThalovantControlPlane.
HTTP 401 with ErrorCode mfa_required Pass otpCode or recoveryCode to api.LoginAsync(...).
API access requires a paid plan Upgrade the workspace before provisioning private resources through the API.
ThalovantUnsupportedProtocolException The hub does not expose WSS, or the code requested Https or Mqtt, which this release does not connect over.
ThalovantIdentityException The identity file is malformed or readable by other users.