Skip to main content

SDKs

.NET Integration

Call your Verdictan gateway from .NET with the built-in HttpClient. You run one request from a console app, then move the same client into an ASP.NET service with IHttpClientFactory.

Before you start​

  • A running gateway from the quickstart, with its application token and a configured model.
  • .NET 8 or newer.

Configure the client​

Set three variables where the service runs:

export VERDICTAN_GATEWAY_URL="http://127.0.0.1:41002/v1"
export VERDICTAN_CLIENT_TOKEN="<application-token>"
export VERDICTAN_MODEL="<configured-model>"

If the gateway runs on another host, use its base URL instead, still ending in /v1. The provider key stays on the gateway, and the application token stays on your server.

Create a console project:

dotnet new console -o VerdictanExample
cd VerdictanExample

Send a request​

Replace Program.cs with:

Program.cs
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;

string Required(string name) => Environment.GetEnvironmentVariable(name)
    is string value && !string.IsNullOrWhiteSpace(value)
        ? value : throw new InvalidOperationException($"Set {name}");

using var client = new HttpClient
{
    BaseAddress = new Uri(Required("VERDICTAN_GATEWAY_URL").TrimEnd('/') + "/"),
    Timeout = TimeSpan.FromSeconds(60)
};
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Required("VERDICTAN_CLIENT_TOKEN"));

using var response = await client.PostAsJsonAsync("chat/completions", new
{
    model = Required("VERDICTAN_MODEL"),
    messages = new[] { new { role = "user", content = "Reply with Hello." } }
});
Console.WriteLine("Request ID: " +
    (response.Headers.TryGetValues("x-request-id", out var ids) ? ids.First() : "unavailable"));
if (!response.IsSuccessStatusCode)
{
    Console.Error.WriteLine($"Request failed: HTTP {(int)response.StatusCode}. Check Verdictan.");
    Environment.ExitCode = 1;
    return;
}
if (response.Headers.TryGetValues("x-verdictan-verdict", out var verdicts)
    && verdicts.Contains("ESCALATE"))
{
    Console.WriteLine("Waiting for human review. Do not resend yet.");
    return;
}

using var body = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var choices = body.RootElement.GetProperty("choices");
if (choices.GetArrayLength() == 0)
    throw new InvalidOperationException("No choices. Check the request in Verdictan.");
var content = choices[0].GetProperty("message").GetProperty("content");
if (content.ValueKind != JsonValueKind.String || string.IsNullOrEmpty(content.GetString()))
    throw new InvalidOperationException("No text answer. Check the request in Verdictan.");
Console.WriteLine(content.GetString());
dotnet run

You see a request ID and a short answer. The trailing / added to BaseAddress matters: without it, .NET drops /v1 when it resolves the relative chat/completions path.

Use it in ASP.NET​

  1. Register a named client in Program.cs, before builder.Build():

    builder.Services.AddHttpClient("Verdictan", client =>
    {
        var url = builder.Configuration["VERDICTAN_GATEWAY_URL"]
            ?? throw new InvalidOperationException("Set VERDICTAN_GATEWAY_URL");
        var token = builder.Configuration["VERDICTAN_CLIENT_TOKEN"]
            ?? throw new InvalidOperationException("Set VERDICTAN_CLIENT_TOKEN");
        client.BaseAddress = new Uri(url.TrimEnd('/') + "/");
        client.DefaultRequestHeaders.Authorization =
            new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
        client.Timeout = TimeSpan.FromSeconds(60);
    });
  2. Inject IHttpClientFactory into your service and call CreateClient("Verdictan").

  3. Pass the incoming request's cancellation token to PostAsJsonAsync, and keep the status, escalation, and content checks from the console example.

Handle gateway decisions​

Every response carries x-verdictan-verdict and x-verdictan-reason-code headers. Handle these cases:

ResponseWhat it meansWhat to do
200 with x-verdictan-verdict: ESCALATEA policy sent the request for human review. Content is null and finish_reason is content_filter.Tell the user it is under review. Don't resend.
400 with code content_policy_violationA policy blocked the request.Show a refusal. Other 400 codes are malformed requests.
401 or 403The token is missing, revoked, or not allowed.Check the application token and its access.
402A budget or balance limit.Check the error code.
429A rate limit.Honor Retry-After if present, within your retry limit.
Timeout or 5xxThe gateway or provider failed.Investigate before a retry: the provider may have already processed the request.

A 200 without text can also be a tool call, so don't treat every empty answer as an escalation. The example makes one attempt. See Error Handling for the full list.

Find the request in Verdictan​

Open History in your organization and search for the printed request ID. Request content is visible only when capture is on in the assigned configuration. Without capture, find the decision in the delivered gateway events.

Next steps​