Skip to Content
SDKsC# SDK

C# SDK (Auris.Licensing)

Auris.Licensing is the official .NET client library for the Auris Licensing module. It targets netstandard2.0, has zero external dependencies (no NuGet references — manual JSON parsing throughout), and implements the full licensing surface: key validation, device activation and deactivation, metered usage recording, floating seat checkout, and offline activation.

This package covers the Licensing module only. It does not provide IAM functionality (user authentication, OIDC, roles, MFA, or the Management API). For full IAM coverage in .NET applications use the Auris REST API directly with a standard OAuth2 library, or reach out for integration guidance.

Target framework: netstandard2.0
External dependencies: none
Namespace: Auris.Licensing


Installation

dotnet add package Auris.Licensing

Or add the reference manually in your project file:

<PackageReference Include="Auris.Licensing" Version="1.0.0" />

AurisLicenseClient

AurisLicenseClient is the single entry point for all licensing operations. It implements IDisposable — wrap it in a using block or register it as a singleton in your DI container.

Constructor

using Auris.Licensing; var client = new AurisLicenseClient( tenantDomain: "auth.yourdomain.com", // required — your Auris tenant domain, without https:// timeoutSeconds: 10 // optional — HTTP timeout (default: 10) );

The client sets the base URL to https://{tenantDomain} and attaches the x-tenant header to every outbound request. No API key is required at the SDK level — the tenant domain identifies the tenant.


Key Validation

ValidateAsync

Validates a license key against the Auris API and returns the full validation result, including the licensee, plan, capacity counters, enabled features, and entitlement metadata.

ValidationResult result = await client.ValidateAsync("LIC-XXXX-XXXX-XXXX"); Console.WriteLine(result.Valid); // bool Console.WriteLine(result.PlanName); // string Console.WriteLine(result.Licensee.Id); // string Console.WriteLine(result.Licensee.Type); // string ("user" or "org")

Signature:

Task<ValidationResult> ValidateAsync(string key, CancellationToken ct = default)

Device Activation

ActivateAsync

Activates a license key on a specific device fingerprint. The fingerprint uniquely identifies the machine (you generate it — typically a hash of hardware identifiers). An optional human-readable name can be attached to the device record in the Auris console.

Device device = await client.ActivateAsync( key: "LIC-XXXX-XXXX-XXXX", fingerprint: "sha256-of-machine-id", name: "Alice's Workstation" // optional ); Console.WriteLine(device.Id); // string — device record ID in Auris Console.WriteLine(device.Fingerprint); // string

Signature:

Task<Device> ActivateAsync( string key, string fingerprint, string? name = null, CancellationToken ct = default )

DeactivateAsync

Releases a device activation, freeing the slot for reuse on another machine.

await client.DeactivateAsync( key: "LIC-XXXX-XXXX-XXXX", fingerprint: "sha256-of-machine-id" );

Signature:

Task DeactivateAsync(string key, string fingerprint, CancellationToken ct = default)

Metered Usage

RecordUsageAsync

Records consumption of a metered metric (for example, API calls processed, documents generated, or gigabytes stored). If amount is omitted the API increments the counter by 1.

UsageRecord record = await client.RecordUsageAsync( key: "LIC-XXXX-XXXX-XXXX", metric: "api_calls", amount: 50L // optional — defaults to 1 ); Console.WriteLine(record.Metric); // string Console.WriteLine(record.Amount); // long Console.WriteLine(record.Timestamp); // DateTimeOffset

Signature:

Task<UsageRecord> RecordUsageAsync( string key, string metric, long? amount = null, CancellationToken ct = default )

GetUsageAsync

Retrieves all metered usage counters for a license key, keyed by metric name.

Dictionary<string, UsageMetric> usage = await client.GetUsageAsync("LIC-XXXX-XXXX-XXXX"); if (usage.TryGetValue("api_calls", out var metric)) { Console.WriteLine($"Used: {metric.Used} / {metric.Max}"); Console.WriteLine($"Resets at: {metric.ResetsAt}"); Console.WriteLine($"Period: {metric.Period}"); // "day", "month", or "forever" }

Signature:

Task<Dictionary<string, UsageMetric>> GetUsageAsync(string key, CancellationToken ct = default)

Feature Flags

CheckFeatureAsync

Returns true if the license grants access to the named feature. Use this for gating functionality that is enabled or disabled per plan.

bool hasAdvancedReporting = await client.CheckFeatureAsync( key: "LIC-XXXX-XXXX-XXXX", feature: "advanced_reporting" ); if (!hasAdvancedReporting) { // Disable or hide the feature in the UI }

Signature:

Task<bool> CheckFeatureAsync(string key, string feature, CancellationToken ct = default)

Floating Seats

Floating seats allow a fixed number of concurrent users to share a single license. Users check out a seat when they begin work and check it back in when done. An optional lease duration limits how long a seat stays checked out without a heartbeat.

CheckoutAsync

Reserves a seat for the given user. Returns the Seat record including its expiry time.

Seat seat = await client.CheckoutAsync( key: "LIC-XXXX-XXXX-XXXX", userId: "usr_alice", leaseDurationMin: 60 // optional — lease expires after 60 minutes without heartbeat ); Console.WriteLine(seat.UserId); // string Console.WriteLine(seat.ExpiresAt); // DateTimeOffset?

Signature:

Task<Seat> CheckoutAsync( string key, string userId, int? leaseDurationMin = null, CancellationToken ct = default )

CheckinAsync

Releases a previously checked-out seat, freeing it immediately for another user.

await client.CheckinAsync( key: "LIC-XXXX-XXXX-XXXX", userId: "usr_alice" );

Signature:

Task CheckinAsync(string key, string userId, CancellationToken ct = default)

HeartbeatAsync

Extends the lease on an active seat. Call this periodically (for example, every 15 minutes) from long-running sessions to prevent the seat from expiring and being reclaimed.

Seat seat = await client.HeartbeatAsync( key: "LIC-XXXX-XXXX-XXXX", userId: "usr_alice", leaseDurationMin: 60 // optional — reset the lease to another 60 minutes );

Signature:

Task<Seat> HeartbeatAsync( string key, string userId, int? leaseDurationMin = null, CancellationToken ct = default )

Offline Licensing

Offline activation is a two-step process: the client generates a request payload, the user submits it to the Auris portal to obtain a signed JWT response, and the client validates that response locally. No network call is made during ValidateOfflineResponse — the JWT signature is not verified; only the exp claim is checked.

GenerateOfflineRequest

Produces a base64-encoded request payload that the user submits to the Auris console to obtain an offline license response. This method is synchronous.

string requestPayload = client.GenerateOfflineRequest( key: "LIC-XXXX-XXXX-XXXX", fingerprint: "sha256-of-machine-id", machineName: "Alice's Workstation" // optional ); // Present requestPayload to the user. They paste it into the Auris portal // and download the response string.

Signature:

string GenerateOfflineRequest(string key, string fingerprint, string? machineName = null)

ValidateOfflineResponse

Decodes and validates the JWT returned by the Auris portal. Throws AurisLicensingException if the token is expired or cannot be decoded.

string responseJwt = /* string obtained from the Auris portal */; ValidationResult result = client.ValidateOfflineResponse(responseJwt); Console.WriteLine(result.Valid); Console.WriteLine(result.PlanName);

Signature:

ValidationResult ValidateOfflineResponse(string responseData)

ASP.NET Example

A complete example validating a license key in an ASP.NET Core Minimal API, with the client registered as a singleton and cancellation token forwarding:

// Program.cs using Auris.Licensing; var builder = WebApplication.CreateBuilder(args); // Register as a singleton — AurisLicenseClient is thread-safe builder.Services.AddSingleton(new AurisLicenseClient( tenantDomain: builder.Configuration["Auris:TenantDomain"]!, timeoutSeconds: 10 )); var app = builder.Build(); app.MapPost("/api/activate", async ( ActivationRequest req, AurisLicenseClient licenseClient, CancellationToken ct ) => { try { // 1. Validate the key first var validation = await licenseClient.ValidateAsync(req.LicenseKey, ct); if (!validation.Valid) return Results.BadRequest(new { error = "License key is not valid." }); // 2. Activate this device var device = await licenseClient.ActivateAsync( key: req.LicenseKey, fingerprint: req.MachineFingerprint, name: req.MachineName, ct: ct ); return Results.Ok(new { activated = true, deviceId = device.Id, plan = validation.PlanName, licensee = validation.Licensee.Id, }); } catch (AurisLicensingException ex) when (ex.StatusCode == 422) { return Results.UnprocessableEntity(new { error = "Device limit reached for this license." }); } catch (AurisLicensingException ex) { return Results.Problem( title: "Licensing error", detail: ex.Message, statusCode: ex.StatusCode ); } }); app.MapPost("/api/validate", async ( ValidateRequest req, AurisLicenseClient licenseClient, CancellationToken ct ) => { var result = await licenseClient.ValidateAsync(req.LicenseKey, ct); return Results.Ok(new { valid = result.Valid, plan = result.PlanName, licensee = result.Licensee?.Id, }); }); app.Run(); record ActivationRequest(string LicenseKey, string MachineFingerprint, string? MachineName); record ValidateRequest(string LicenseKey);

Model Types

TypeProperties
ValidationResultValid (bool), PlanName (string), Licensee (Licensee), Capacity (CapacityCounter), Features (string[]), Metadata (Dictionary)
LicenseeId (string), Type (string)
CapacityCounterUsed (int), Max (int)
UsageMetricUsed (long), Max (long?), Period (string), ResetsAt (DateTimeOffset?)
DeviceId (string), Fingerprint (string), Name (string?), CreatedAt (DateTimeOffset)
UsageRecordMetric (string), Amount (long), Timestamp (DateTimeOffset)
SeatUserId (string), CheckedOutAt (DateTimeOffset), ExpiresAt (DateTimeOffset?)

Error Handling

All async methods throw AurisLicensingException on any non-2xx response. The synchronous methods (GenerateOfflineRequest, ValidateOfflineResponse) throw AurisLicensingException for decoding failures.

using Auris.Licensing; try { var result = await client.ValidateAsync("LIC-XXXX-XXXX-XXXX"); } catch (AurisLicensingException ex) { Console.Error.WriteLine($"HTTP {ex.StatusCode}: {ex.Message}"); // StatusCode examples: // 404 — key not found // 422 — device limit reached, usage limit exceeded // 410 — key expired or revoked // 503 — Auris API unreachable (network error wrapped as 0) }
StatusCodeMeaning
404License key not found
410License key expired or revoked
422Validation failed (device limit, usage cap, feature not enabled)
0Network or serialization error (no HTTP response received)

  • Swift SDK — Licensing client for Apple platform applications
  • JavaScript SDK — Full IAM SDK for browsers and Node.js
  • Next.js SDK — Server-side IAM helpers for Next.js
  • Licensing Guide — Key types, capacity counters, metered billing, and floating seats