Satya.Sdk
1.0.1
dotnet add package Satya.Sdk --version 1.0.1
NuGet\Install-Package Satya.Sdk -Version 1.0.1
<PackageReference Include="Satya.Sdk" Version="1.0.1" />
<PackageVersion Include="Satya.Sdk" Version="1.0.1" />
<PackageReference Include="Satya.Sdk" />
paket add Satya.Sdk --version 1.0.1
#r "nuget: Satya.Sdk, 1.0.1"
#:package Satya.Sdk@1.0.1
#addin nuget:?package=Satya.Sdk&version=1.0.1
#tool nuget:?package=Satya.Sdk&version=1.0.1
Satya.Sdk
Official .NET SDK for the Satya API.
This SDK provides a strongly-typed, production-ready client for interacting with Satya services, including authentication, vetting, and reports.
Installation
Install the SDK via NuGet:
dotnet add package Satya.Sdk
Authentication Model (Machine-to-Machine)
This SDK uses a machine-to-machine (M2M) authentication flow.
Each customer owns:
- Project ID – configured once when creating the client, can be found in Satya application under /settings/account-profile
- Access Key – stored securely by the customer
The SDK exchanges the access key for a short-lived JWT and automatically manages re-login when needed.
Important Rules
- You must explicitly log in once before calling protected endpoints
- Calling a protected endpoint before login results in a local 401 Unauthorized
- No HTTP request is sent when the JWT is missing
- After login, the SDK automatically re-logins when the JWT is near expiration or expired
- The access key is stored in-memory only and is never persisted by the SDK
Quick Start
Create the client:
using Satya.Sdk;
using Satya.Sdk.Vet;
var client = new SatyaClient(new SatyaClientOptions
{
ProjectId = "your-project-id"
});
Perform mandatory login:
await client.Auth.LoginAndSetTokenAsync("YOUR_ACCESS_KEY");
Call a protected endpoint:
var vettingItem = new VetRequestDto
{
Name = "John Doe",
CountryIsoCode = "US",
ImageBase64 = "base64-encoded-image"
};
var vet = await client.Vet.VetAsync(vettingItem);
API Versioning
- The SDK builds URLs as
"{BaseUrl}/api/{ApiVersion}/..."; defaultApiVersionisv1(backward compatible with unversioned routes on the server). - An optional
EnableCompatibilityCheck(defaultfalse) calls/api/metaonce to verify the server’s major version matches the SDK’s expected major. Enable it to enforce compatibility; disable if your server does not expose/api/meta. - The server meta endpoint supports both
/api/metaand/api/v1/meta; property names are stable (service,apiMajor,apiMinor,apiPatch,supportedMajors).
Authentication Flow
The user calls:
client.Auth.LoginAndSetTokenAsync(accessKey);The SDK calls the M2M login endpoint and stores:
- JWT value
- JWT expiration time (UTC)
- Access key (in memory)
For every protected request:
- The JWT is attached as
Authorization: Bearer <token> - If the JWT is close to expiration, the SDK re-logins automatically
- If the API responds with
code = jwt_expired, the SDK re-logins and retries once
- The JWT is attached as
Automatic Re-Login Rules
The SDK WILL re-login automatically when:
The JWT expiration time is approaching (proactive refresh)
The API responds with:
{ "code": "jwt_expired", "message": "Token is expired or near expiration, please re-login or refresh" }
The SDK WILL NOT re-login automatically when:
- The JWT is missing
- The JWT is invalid
- The authorization scheme is incorrect
In these cases, the error is surfaced directly to the caller.
Error Handling
The SDK is designed to throw exceptions and let the consuming application decide how to handle them
(retry, log, show user feedback, persist state, etc.).
Exception taxonomy (what to expect)
SDK consumers should handle errors according to the following rules.
1. ArgumentException — local validation failures (no HTTP call)
Thrown before any request is sent when the payload is invalid:
- Missing/empty
Name - Missing/empty
ImageBase64 - Invalid
CountryIsoCodeformat (does not match 2–3 uppercase letters with optional “-” + 2–3 uppercase letters) - Null request object
2. ApiException — all Satya SDK / API failures
ApiException is the primary exception type thrown by the Satya SDK.
It is declared in the Satya.Sdk.Internal namespace, so add using Satya.Sdk.Internal; in files that catch it.
It represents all expected failures that can occur while using the SDK, including:
- API errors (
4xx/5xx) - Authentication issues (missing or expired credentials)
- HTTP request timeouts
- Automatic re-login failures
- Vetting wait timeouts (when a vet remains
Pendingpast the wait limit)
Key properties
Each ApiException exposes the following information:
StatusCode
HTTP status code (or logical equivalent for SDK-level errors)Message
High-level, human-readable description of the failureResponseBody
Raw API response body (when available), useful for diagnostics and logging
Example handling
catch (ApiException ex)
{
Console.WriteLine($"Satya error: {(int)ex.StatusCode} {ex.StatusCode}");
Console.WriteLine(ex.Message);
if (!string.IsNullOrWhiteSpace(ex.ResponseBody))
{
Console.WriteLine("API response:");
Console.WriteLine(ex.ResponseBody);
}
// Either rethrow, or map to your application's domain-specific error model
throw;
}
Common ApiException.StatusCode values
| Status Code | Meaning | Recommended Handling |
|---|---|---|
400 BadRequest |
Request validation failed, or the tenant query limit was reached | Correct the payload; for quota, wait for the reset or contact your account team |
401 Unauthorized |
Not logged in / invalid access key | Re-run login or fail fast |
404 NotFound |
No vetting record for the supplied PersonId in the active tenant |
Verify the PersonId returned by the vet request |
408 RequestTimeout |
HTTP request timed out, or a vet stayed Pending past the wait timeout |
Retry later or increase the timeout |
415 UnsupportedMediaType |
Request was not sent as application/json |
Should not occur via the SDK; report it if it does |
5xx |
Server error | Treat as transient |
3. Vetting wait timeout (RequestTimeout)
When using:
VetAndWaitAsyncWaitForFinalStatusAsync
If the vetting process remains Pending past the configured wait timeout, the SDK throws:
ApiExceptionStatusCode = RequestTimeout (408)
This does NOT mean failure — only that vetting is still in progress.
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.RequestTimeout)
{
// Vetting is still pending.
// Persist PersonId and retry later or continue polling.
}
4. Network-level failures
Low-level network issues (DNS, TLS, connection refused) may surface as:
HttpRequestException
These are typically transient.
catch (HttpRequestException ex)
{
// Network failure (DNS, TLS, connection refused).
// Retry or fail depending on your application logic.
throw;
}
5. Unexpected exceptions
Any other exception indicates:
- a bug
- invalid environment
- unexpected runtime failure
These should generally be logged and escalated.
catch (Exception ex)
{
// Unexpected failure
// Log with stack trace and escalate
throw;
}
Recommended catch order (summary)
try
{
await client.Auth.LoginAndSetTokenAsync(accessKey);
var vetResult = await client.Vet.VetAndWaitAsync(request);
// Handle final result (Cleared / Suspected)
}
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.RequestTimeout)
{
// Vetting still pending – retry later or continue polling
}
catch (ApiException ex)
{
// Satya API / SDK failure
throw;
}
catch (HttpRequestException)
{
// Network failure
throw;
}
catch (Exception)
{
// Unexpected failure
// Log with stack trace and escalate
throw;
}
Key principles
- The SDK never swallows errors
- All expected failures surface as
ApiException - Retry logic belongs in the consuming application
- The SDK provides maximum diagnostic information, not policy
Logout
To clear authentication state:
client.Auth.Logout();
After logout, protected calls will again fail with a local 401 until login is performed.
Configuration
SatyaClientOptions controls how the SDK communicates with the Satya API.
These options are provided once during client creation.
Available options
ProjectId(required)
Customer-specific project identifier.
This value uniquely identifies your project and can be found in the Satya application under:
/settings/account-profileBaseUrl(optional)
Base URL of the Satya API.
The SDK is preconfigured with the correct production URL by default.
This value should NOT be changed unless you were explicitly instructed to do so by the Satya team
(for example, when using a private deployment, dedicated region, or internal testing environment).Timeout(optional)
Default timeout applied to all HTTP requests made by the SDK.
The default value is 3 minutes, which is suitable for long-running operations such as vetting and report generation.
You may override this value if your application requires a shorter or longer timeout.ApiVersion(optional)
API version suffix used when building routes (default:v1).
URLs are composed as{BaseUrl}/api/{ApiVersion}/.... Keep the default unless you are explicitly asked to target a different API version.EnableCompatibilityCheck(optional)
Whentrue, the SDK calls/api/metaonce to verify the server major version matchesApiVersion.
Default isfalse. Enable to enforce compatibility; disable if your server does not expose/api/meta.
Minimal configuration (recommended)
Use this configuration in almost all production scenarios.
var options = new SatyaClientOptions
{
ProjectId = "your-project-id"
};
using var client = new SatyaClient(options);
Advanced configuration (only when needed)
Override defaults only when required by your environment or application constraints.
var options = new SatyaClientOptions
{
ProjectId = "your-project-id",
// Change BaseUrl only if explicitly instructed by Satya
BaseUrl = new Uri("https://api.your-domain.com"),
// Override the default 3-minute timeout if needed
Timeout = TimeSpan.FromMinutes(5)
};
using var client = new SatyaClient(options);
Thread Safety
- The SDK is safe for concurrent use
- Only one re-login operation is performed even if multiple requests detect expiration simultaneously
Versioning
This SDK follows Semantic Versioning:
- Patch (
x.y.Z) – bug fixes - Minor (
x.Y.z) – backward-compatible features - Major (
X.y.z) – breaking changes
Requirements
- .NET 8 or newer (the package targets
net8.0) - Valid access key and project ID issued by the customer.
Support
For questions, issues, or feature requests:
- Email: support@satya.digital
- Docs: https://app.satya.digital/docs/
Usage
This section explains how to use the SDK end-to-end, from submitting a vet request to downloading the final report to a local file.
You can choose between:
- VetAndWaitAsync – submit and wait in a single call (recommended)
- VetAsync + WaitForFinalStatusAsync – submit first, then wait explicitly
Default waiting behavior:
- Poll interval: 5 minutes
- Timeout: 24 hours
1. Install and import
Install the SDK via NuGet and import the required namespaces.
using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Satya.Sdk; // SatyaClient, SatyaClientOptions
using Satya.Sdk.Vet; // VetRequestDto, VetResponseDto, VetStatus
using Satya.Sdk.Internal; // ApiException
2. Create the SDK client
Create the client once and reuse it for all vetting operations.
var options = new SatyaClientOptions
{
ProjectId = "your-project-id"
};
using var client = new SatyaClient(options);
3. Login
Perform mandatory login.
await client.Auth.LoginAndSetTokenAsync("YOUR_ACCESS_KEY");
4. Build the vet request
Prepare the vet request with the subject’s identifying information.
var vettingItem = new VetRequestDto
{
Name = "John Doe",
CountryIsoCode = "US",
ImageBase64 = "base64-encoded-image"
};
Input requirements (VetRequestDto):
- Name (required): must not be empty.
- CountryIsoCode (optional): 2–3 uppercase letters, optional dash + 2–3 uppercase letters for region (e.g. US, USA, US-NY, USA-NY, US-NYC, USA-NYC).
- ImageBase64 (required): valid Base64-encoded image string (raw bytes; no data URI prefix).
Option A (Recommended): Vet and wait in one call
Use VetAndWaitAsync when you want the SDK to handle polling internally and return only a final result.
- Blocks until the vet reaches a final state
- Final states are typically
ClearedorSuspected - Uses default polling (every 5 minutes, up to 24 hours)
- Throws on failure or timeout
VetResponseDto vetResult = await client.Vet.VetAndWaitAsync(
vettingItem
);
Console.WriteLine($"Final status: {vetResult.VetStatus}");
Option B: Submit first, then wait explicitly
Use this approach when you need the PersonId immediately (for persistence, correlation, or later reuse).
5. Submit the vet request
VetResponseDto vetResult = await client.Vet.VetAsync(
vettingItem
);
Console.WriteLine(
$"Submitted vet. PersonId={vetResult.PersonId}, Status={vetResult.VetStatus}"
);
6. Wait for the final status
WaitForFinalStatusAsync:
- Returns immediately if the status is already final
- Polls automatically if the status is
Pending - Uses default polling (every 5 minutes, up to 24 hours)
if (vetResult.VetStatus is VetStatus.Pending)
{
vetResult = await client.Vet.WaitForFinalStatusAsync(
vetResult.PersonId
);
}
Console.WriteLine($"Final status: {vetResult.VetStatus}");
7. Handle the final status
After either waiting approach, the vet result is guaranteed to be final.
switch (vetResult.VetStatus)
{
case VetStatus.Cleared:
// Handle Cleared status scenario
Console.WriteLine("Vetting completed: CLEARED");
break;
case VetStatus.Suspected:
// Handle Suspected status scenario
Console.WriteLine("Vetting completed: SUSPECTED");
break;
default:
throw new InvalidOperationException(
$"Unexpected final status: {vetResult.VetStatus}");
}
Output (VetResponseDto):
- PersonId: unique identifier of the vetted person; use to poll or correlate.
- VetStatus:
Cleared,Pending,Suspected, orNotVetted. OnlyClearedandSuspectedare treated as final by the wait helpers, soPendingshould not appear after a wait. - ReportUrl: single pre-signed report link, valid for 5 minutes; download within that window.
It points to the in-depth report when
Suspectedand the essential report whenCleared. It is empty whilePending, and also when your project is not permitted to receive reports. - Vetting: list of findings/decisions (populated when
Suspected; empty forCleared).
8. Download the report to a local file
Once the vet reaches a final status (Cleared or Suspected), download the report using the provided report URL.
// Download the report to a local file
if (!string.IsNullOrWhiteSpace(vetResult.ReportUrl))
{
string directory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"Satya",
"Reports"
);
string fileName =
$"{vettingItem.Name}_" +
$"{DateTime.UtcNow:yyyy-MM-dd_HH-mm-ss_fff}.pdf";
string fullPath = Path.Combine(directory, fileName);
await client.Report.DownloadReportToFileAsync(vetResult.ReportUrl, fullPath);
Console.WriteLine($"Report saved to: {fullPath}");
}
ReportUrl is signed for 5 minutes, so download it as soon as the vet reaches a final status
rather than persisting the URL for later use.
Full end-to-end example (recommended)
Submit → wait → validate result → download report.
public static async Task RunAsync()
{
var options = new SatyaClientOptions
{
ProjectId = "your-project-id"
};
using var client = new SatyaClient(options);
await client.Auth.LoginAndSetTokenAsync("YOUR_ACCESS_KEY");
var vettingItem = new VetRequestDto
{
Name = "John Doe",
CountryIsoCode = "US",
ImageBase64 = "base64-encoded-image"
};
#region Option A
VetResponseDto vetResult = await client.Vet.VetAndWaitAsync(
vettingItem
);
#endregion
#region Option B
//VetResponseDto vetResult = await client.Vet.VetAsync(
// vettingItem
//);
//if (vetResult.VetStatus is VetStatus.Pending)
//{
// vetResult = await client.Vet.WaitForFinalStatusAsync(
// vetResult.PersonId
// );
//}
#endregion
switch (vetResult.VetStatus)
{
case VetStatus.Cleared:
// Handle Cleared status scenario
Console.WriteLine("Vetting completed: CLEARED");
break;
case VetStatus.Suspected:
// Handle Suspected status scenario
Console.WriteLine("Vetting completed: SUSPECTED");
break;
default:
throw new InvalidOperationException(
$"Unexpected final status: {vetResult.VetStatus}");
}
// Download the report to a local file
if (!string.IsNullOrWhiteSpace(vetResult.ReportUrl))
{
string directory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"Satya",
"Reports"
);
string fileName =
$"{vettingItem.Name}_" +
$"{DateTime.UtcNow:yyyy-MM-dd_HH-mm-ss_fff}.pdf";
string fullPath = Path.Combine(directory, fileName);
await client.Report.DownloadReportToFileAsync(vetResult.ReportUrl, fullPath);
Console.WriteLine($"Report saved to: {fullPath}");
}
}
Summary
- Prefer VetAndWaitAsync for the simplest integration
- Use VetAsync + WaitForFinalStatusAsync when you need lifecycle control
- Always handle final statuses explicitly
- Reports are downloaded via
Report.DownloadReportToFileAsync
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Documentation-only release; no API or behavior changes. Corrected README samples to use VetStatus and ReportUrl, added the required using directives, replaced the nonexistent 429 entry in the ApiException status code table with 400/404/415, and raised the stated minimum from .NET 6 to .NET 8. VetAndWaitAsync and WaitForFinalStatusAsync XML docs now correctly document ApiException with StatusCode RequestTimeout (408) instead of TimeoutException.