Licensing in Any Language
The Auris Licensing API is a standard REST/JSON API. You don’t need an SDK — any language that can make an HTTP POST and parse JSON can validate licenses, activate devices, and gate features.
If you’re using JavaScript/TypeScript, use the @auris/js SDK instead — it handles offline fallback and revocation caching automatically.
The Only Endpoint You Need
POST https://your-auris-domain/api/licensing/validate
// Request
{
"key": "VIG-A8BC-D3EF-G4HJ-K5LM"
}
// Response (valid)
{
"valid": true,
"features": ["threat-intel", "vuln-scan"],
"seats": { "used": 1, "max": 5 },
"expiresAt": "2027-03-15T00:00:00Z"
}
// Response (invalid)
{
"valid": false,
"reason": "EXPIRED"
}Headers: Content-Type: application/json and x-tenant: your-tenant-id (optional, defaults to your-tenant-id).
No Bearer token needed. This is a public endpoint.
Language Examples
C#
C# (.NET)
using System.Net.Http;
using System.Text;
using System.Text.Json;
public record LicenseResult(bool Valid, string? Reason, string[]? Features, DateTime? ExpiresAt);
public class AurisLicense
{
private static readonly HttpClient _http = new();
private readonly string _baseUrl;
private readonly string _tenant;
public AurisLicense(string domain, string tenant = "your-tenant-id")
{
_baseUrl = $"https://{domain}";
_tenant = tenant;
}
public async Task<LicenseResult> ValidateAsync(string key)
{
var request = new HttpRequestMessage(HttpMethod.Post, $"{_baseUrl}/api/licensing/validate")
{
Content = new StringContent(
JsonSerializer.Serialize(new { key }),
Encoding.UTF8, "application/json")
};
request.Headers.Add("x-tenant", _tenant);
var response = await _http.SendAsync(request);
var json = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<LicenseResult>(json,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!;
}
public async Task ActivateAsync(string key, string fingerprint, string? name = null)
{
var request = new HttpRequestMessage(HttpMethod.Post, $"{_baseUrl}/api/licensing/activate")
{
Content = new StringContent(
JsonSerializer.Serialize(new { key, fingerprint, name }),
Encoding.UTF8, "application/json")
};
request.Headers.Add("x-tenant", _tenant);
var response = await _http.SendAsync(request);
if (!response.IsSuccessStatusCode)
throw new Exception($"Activation failed: {response.StatusCode}");
}
public async Task DeactivateAsync(string key, string fingerprint)
{
var request = new HttpRequestMessage(HttpMethod.Post, $"{_baseUrl}/api/licensing/deactivate")
{
Content = new StringContent(
JsonSerializer.Serialize(new { key, fingerprint }),
Encoding.UTF8, "application/json")
};
request.Headers.Add("x-tenant", _tenant);
await _http.SendAsync(request);
}
}Usage:
var license = new AurisLicense("auth.yourdomain.com", "your-tenant-id");
// Validate
var result = await license.ValidateAsync("VIG-A8BC-D3EF-G4HJ-K5LM");
if (result.Valid)
{
Console.WriteLine($"Valid! Features: {string.Join(", ", result.Features ?? [])}");
}
// Activate device
await license.ActivateAsync("VIG-A8BC-D3EF-G4HJ-K5LM", GetMachineId(), Environment.MachineName);
// Feature gating
if (result.Features?.Contains("threat-intel") == true)
{
// Enable threat intel module
}curl
For testing or shell scripts:
# Validate
curl -s -X POST https://auth.yourdomain.com/api/licensing/validate \
-H "Content-Type: application/json" \
-H "x-tenant: your-tenant-id" \
-d '{"key": "VIG-A8BC-D3EF-G4HJ-K5LM"}' | jq
# Activate device
curl -s -X POST https://auth.yourdomain.com/api/licensing/activate \
-H "Content-Type: application/json" \
-H "x-tenant: your-tenant-id" \
-d '{"key": "VIG-A8BC-D3EF-G4HJ-K5LM", "fingerprint": "abc123", "name": "Dev Machine"}'
# Deactivate device
curl -s -X POST https://auth.yourdomain.com/api/licensing/deactivate \
-H "Content-Type: application/json" \
-H "x-tenant: your-tenant-id" \
-d '{"key": "VIG-A8BC-D3EF-G4HJ-K5LM", "fingerprint": "abc123"}'Offline Validation (JWT)
When a key is issued, it comes with a jwtToken — a signed JWT containing the entitlements. For offline validation without the SDK, decode the JWT payload (base64url) and check:
- Expiry:
expclaim (Unix timestamp) must be in the future - Revocation: Fetch
/api/licensing/revocation-listperiodically and check if the JWT’sjtiis in the revoked list - Entitlements:
auris_lic.features,auris_lic.seats.max,auris_lic.devices.max
// JWT payload (decoded)
{
"jti": "key_abc123",
"iss": "auris",
"sub": "VIG-A8BC-D3EF-G4HJ-K5LM",
"exp": 1804723200,
"auris_lic": {
"features": ["threat-intel", "vuln-scan"],
"seats": { "max": 5 },
"devices": { "max": 3 }
}
}For full offline validation with signature verification, use the Auris public key from /api/.well-known/jwks.json. Most languages have JWT libraries (e.g. System.IdentityModel.Tokens.Jwt for C#, jsonwebtoken crate for Rust, golang-jwt for Go).
Device Fingerprinting
For device-based licensing, generate a stable machine identifier:
| Language | Method |
|---|---|
| C# | System.Management → Win32_ComputerSystemProduct.UUID or Environment.MachineName |
| Rust | machine-uid crate or /etc/machine-id on Linux |
| C/C++ | /etc/machine-id (Linux), IOPlatformUUID (macOS), MachineGuid registry (Windows) |
| Go | github.com/denisbrodbeck/machineid |
| Python | uuid.getnode() or platform.node() |
| Java | InetAddress.getLocalHost().getHostName() + MAC address |
The fingerprint just needs to be a stable string unique to the machine. Send it to activate and deactivate.
Summary
The pattern is the same in every language:
1. POST /api/licensing/validate {"key": "..."} → {valid, features, seats, ...}
2. POST /api/licensing/activate {"key": "...", "fingerprint": "..."} → 200 OK
3. POST /api/licensing/deactivate {"key": "...", "fingerprint": "..."} → 200 OKThree endpoints. No SDK required. No API key. No Bearer token. Just HTTP + JSON.