Verification
.NET server SDK
ThirdFactor.SDK — create verification sessions, select workflows, retrieve decisions, and verify signed webhooks from .NET.
The official .NET SDK is a server-only client for the ThirdFactor API. The
NuGet package is ThirdFactor.SDK, and its namespace is ThirdFactor.
Warning
Keep your tenant API key on the server. Never put it in browser code, a mobile application, a desktop client, or a public repository.
Requirements
- .NET 6 or newer; .NET 10 LTS is recommended for new production services
- No runtime dependencies outside the .NET base class library
- A tenant API key from Console → Settings → API keys
Installation
dotnet add package ThirdFactor.SDK --version 0.1.0Create a session and select a workflow
using ThirdFactor;
var thirdFactor = new ThirdFactorClient(
Environment.GetEnvironmentVariable("THIRDFACTOR_API_KEY")!,
"https://your-tenant.thirdfactor.ai"
);
using var session = await thirdFactor.CreateSessionAsync(
new Dictionary<string, object?>
{
["vendor_data"] = "user-42",
["workflow_id"] = "4c615aec-e173-450d-8089-30d4edc835f3",
["callback_url"] = "https://app.example.com/kyc/done",
["contact_email"] = "[email protected]",
["metadata"] = new Dictionary<string, object?>
{
["source"] = "dotnet-sdk"
}
},
idempotencyKey: "kyc-user-42"
);
var sessionId = session.RootElement.GetProperty("id").GetString();
var hostedUrl = session.RootElement.GetProperty("url").GetString();Pass the desired Console workflow UUID as workflow_id. Omit it to use the
tenant's default workflow. Persist the session ID and send only the hosted URL
to the applicant. Use a stable idempotency key for each logical attempt so a
retry returns the original session.
Retrieve a session or decision
using var current = await thirdFactor.RetrieveSessionAsync(sessionId!);
using var decision = await thirdFactor.SessionDecisionAsync(sessionId!);
if (decision.RootElement.GetProperty("decision").GetString() == "approved")
{
GrantAccess();
}The hosted UI result is advisory. Grant access, move money, or provision an account only after a signed webhook or this authenticated decision lookup.
Verify webhooks
Pass the untouched HTTP request bytes and the X-Webhook-Signature header
before deserializing JSON:
using ThirdFactor;
var secret = Environment.GetEnvironmentVariable("THIRDFACTOR_WEBHOOK_SECRET")!;
using var webhookEvent = ThirdFactorWebhooks.ConstructEvent(
rawRequestBody,
signatureHeader,
secret
);The verifier uses constant-time HMAC comparison and rejects signatures outside
the five-minute replay window by default. ConstructEvent throws an
ArgumentException when the signature is invalid, stale, or the body is not
valid JSON.
Handle API errors
try
{
using var decision = await thirdFactor.SessionDecisionAsync(sessionId!);
}
catch (ThirdFactorException error)
{
Console.Error.WriteLine(error.Status);
Console.Error.WriteLine(error.ResponseBody);
Console.Error.WriteLine(error.RequestId);
}