.NET SDK
Use Enlitt from an ASP.NET Core backend or a Unity dedicated server.
The .NET SDK does what the Node.js SDK does, for an ASP.NET Core server or any .NET 8 backend, such as a Unity dedicated server. It comes as three NuGet packages:
| Package | What it holds |
|---|---|
Enlitt | EnlittSdk.WithPremiumChargeAsync, EnlittSdk.UsageAsync, sessions, exceptions, and the login handlers. |
Enlitt.AspNetCore | UseEnlittSession, MapEnlittAuth, and MapEnlittClientSignIn. |
Enlitt.Extensions.AI | EnlittChatClient, a Microsoft.Extensions.AI IChatClient for standard and premium calls. |
Every rule on the other pages applies unchanged. That includes
login, premium limits,
idempotency, and errors. This page shows
only the .NET names. Errors are exceptions, so EnlittLoginRequiredError
becomes EnlittLoginRequiredException.
Install
dotnet add package Enlitt.AspNetCore
dotnet add package Enlitt.Extensions.AIThen wire the project:
npx enlitt setup --name "My .NET app"The CLI needs Node.js. setup finds your .csproj or .sln. It then writes
ENLITT_CLIENT_ID and ENLITT_SECRET_KEY to .env and records the
application in enlitt.json. Keep .env out of git, and load it into the
process environment (for example with your host's environment settings or a
.env loader). The SDK reads ENLITT_SECRET_KEY from the environment.
Mount login and the session middleware
using Enlitt;
using Enlitt.AspNetCore;
using Enlitt.Auth;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var config = new CallbackConfig
{
ClientId = Environment.GetEnvironmentVariable("ENLITT_CLIENT_ID")!,
AppOrigin = "https://your-app.example",
RedirectUri = "https://your-app.example/enlitt/callback",
DefaultReturnTo = "/",
StateStore = new MyStateStore(), // implements IStateStore; share it across instances
// SecretKey defaults to the ENLITT_SECRET_KEY environment variable.
};
app.UseEnlittSession();
app.MapEnlittAuth(config); // /enlitt/login, /enlitt/callback, /enlitt/logoutMapEnlittAuth takes optional path arguments. The callback path must be the
path of RedirectUri. The handlers behave exactly as described on the
login page.
Make a standard call
EnlittChatClient.Standard() is an IChatClient, so it works anywhere
Microsoft.Extensions.AI does:
using Enlitt.Extensions.AI;
using Microsoft.Extensions.AI;
IChatClient standard = EnlittChatClient.Standard();
app.MapPost("/api/summary", async (CancellationToken ct) =>
{
ChatResponse response = await standard.GetResponseAsync("Summarize this support ticket.", cancellationToken: ct);
return Results.Json(new { text = response.Text });
});GetStreamingResponseAsync streams. Cancel a call with the
CancellationToken. The standard model's limits are on the
models page; unsupported ChatOptions, such as Temperature
or a required tool mode, throw EnlittConfigurationException before any
request is sent.
Make a premium call
Wrap your own provider's IChatClient. Your provider key stays on your server:
IChatClient premium = EnlittChatClient.Premium(myProviderChatClient);
var options = new ChatOptions
{
AdditionalProperties = new()
{
["enlitt"] = new EnlittProviderOptions
{
MaxCharge = "20000000", // NANOUSD, as a string
Price = EnlittPricing.PerToken(input: "400", output: "1600"),
},
},
};
ChatResponse response = await premium.GetResponseAsync("Write a long story.", options, ct);The provider and model labels come from the wrapped client's
ChatClientMetadata.
For any other provider (images, voice, another SDK), use
WithPremiumChargeAsync:
byte[] image = await EnlittSdk.WithPremiumChargeAsync(
new WithPremiumChargeOptions
{
MaxCharge = "5000000",
Provider = new PremiumProvider("my-image-provider", "image-v2"),
},
async (charge, operation, ct) =>
{
byte[] result = await myImageProvider.GenerateAsync(prompt, ct);
charge("5000000"); // what this call costs the user, in NANOUSD
return result;
},
ct);The call is reported exactly once. If the delegate returns, it is reported as completed; if it throws, as failed; if its token is cancelled, as cancelled.
Remaining capacity
var capacity = await EnlittSdk.UsageAsync();
Console.WriteLine(capacity.Standard.RemainingPercent);Exceptions
The classes are:
EnlittExceptionEnlittLoginRequiredExceptionEnlittInsufficientCreditsExceptionEnlittLimitExceededExceptionEnlittSubscriptionInactiveExceptionEnlittRateLimitExceptionEnlittAuthenticationExceptionEnlittAuthorizationExceptionEnlittConfigurationException
Each carries Code, ProviderInvoked, Retryable, RetryAfterMs,
RequestId, and AuthorizeUrl. The errors page says which
ones are safe to show a user.
try
{
response = await standard.GetResponseAsync(prompt, cancellationToken: ct);
}
catch (EnlittLoginRequiredException)
{
return Results.Redirect("/enlitt/login?return_to=/chat");
}Background jobs
Outside a request, wrap the work in a session you stored:
await EnlittSdk.RunWithEnlittSessionAsync(new EnlittSession(storedToken), async () =>
{
await standard.GetResponseAsync("Write tonight's digest.");
});Games and native apps
If your server backs a Unity game or a desktop or mobile app, add
app.MapEnlittClientSignIn(...) and
app.UseEnlittSession(new EnlittSessionMiddlewareOptions { Header = true }).
See client sign-in.