Browse the library
Documentation libraryIntegration
C++, C# and Python SDKs
Three native SDKs for desktop software and command-line tools. They speak the same CLV1.1 protocol as the JavaScript SDK: the machine signs every request, your app signs every answer, and offline tokens and update manifests are checked right on the machine.
3 min read
Choosing an SDK
| SDK | Requires | Libraries | Device key |
|---|---|---|---|
| C++ | C++17, CMake, vcpkg | libsodium, libcurl, nlohmann/json | Sealed with DPAPI on Windows |
| C# | .NET 8 or later | BouncyCastle | Sealed with DPAPI on Windows |
| Python | Python 3.9 or later | cryptography | Stored in a file only the current user can read |
All three pass the same test vectors as the server, and have a test that runs them against the real API.
Three integration steps
The app's Integration › Connect software page has sample code for each language, with your App ID and public key already filled in, and a starter project that runs as downloaded. The steps are the same everywhere:
- Create the client with the API address, the App ID, the app's public key, a description of the machine (
default_device,ClavisDevice.Default) and a device key kept between runs. - Call
activatewith the customer's key on first run, orloginif your app uses accounts. - Send a
heartbeatwhile the software runs, waiting the secondsnextCheckIngives between two. Sessions end after 60 minutes without one.
using ClavisAuh;
var clavis = new ClavisClient(new ClavisOptions
{
BaseUrl = "https://api.example.com",
AppId = "app_…",
AppPublicKeys = ["<public key>"],
Device = ClavisDevice.Default(),
DeviceKey = ClavisDevice.LoadOrCreateKey("device.key"),
});
try
{
var grant = await clavis.ActivateAsync(licenseKey);
}
catch (ClavisException e)
{
Console.WriteLine($"Refused: {e.Code}");
}
When an answer cannot be trusted
Every answer must carry the app's signature, match the request just sent and be within 60 seconds. Otherwise the SDK raises a verification error with one of these codes:
| Code | Meaning |
|---|---|
unsigned_response | The answer has no signature |
unknown_key | Signed by a key this build does not trust |
invalid_response_signature | Wrong signature, the content was changed |
stale_response | The answer is too old or too new |
Treat these like no answer at all. After the next valid answer, the SDK reports the failures to Protect 24/7 (the forged signature signal).
Retries and heartbeat pace
The SDKs try again by themselves, with a growing random wait, two more times by default. maxRetries changes that, and 0 turns it off. fallbackUrls lists other addresses of the same server, tried in turn. These names and nextCheckIn below follow your language's spelling.
- No answer, or an unsigned 5xx page: only calls that are safe to repeat (
init,activate,login,heartbeat,variables, update checks,logout, reports).trial,register,redeemandtransferare never repeated after a lost answer, because they may already have happened. - A signed
rate_limited, or an unsigned 429 or 503: any call, obeyingRetry-Afterup to 30 seconds.
Only a verified signature changes license state.
nextCheckIn gives the seconds to wait before the next heartbeat: the server's signed nextCheckSeconds, plus a spread of up to a fifth that stays the same for the machine, so thousands of copies do not call at once.
Offline tokens and updates
- On every plan,
activateandheartbeatreturn an offline token, valid 7 days by default. On Premium the license plan sets the length. It isnullonly while Online-Only Mode is on.verify_offline/VerifyOfflinereturns its content while it is valid on this machine. A token copied to another machine, a clock turned back or a revoked license are all refused. A machine that has not heard of a revocation keeps working offline until the token ends. check_updates/CheckUpdatesAsynconly returns a release manifest signed by your app key and still fresh; the download helper refuses a file whose sha256 does not match.
Rotating the signing key
Pass every public key the build trusts in the key list (app_public_keys, AppPublicKeys). When you prepare a new key in the Signing keys panel, ship a build that carries both keys first, then activate the new key. See Signing keys and rotation.