Skip to Content
GuidesLicensing in Any Language

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# (.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:

  1. Expiry: exp claim (Unix timestamp) must be in the future
  2. Revocation: Fetch /api/licensing/revocation-list periodically and check if the JWT’s jti is in the revoked list
  3. 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:

LanguageMethod
C#System.Management → Win32_ComputerSystemProduct.UUID or Environment.MachineName
Rustmachine-uid crate or /etc/machine-id on Linux
C/C++/etc/machine-id (Linux), IOPlatformUUID (macOS), MachineGuid registry (Windows)
Gogithub.com/denisbrodbeck/machineid
Pythonuuid.getnode() or platform.node()
JavaInetAddress.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 OK

Three endpoints. No SDK required. No API key. No Bearer token. Just HTTP + JSON.