Offline (air-gapped) activation
A machine with intermittent connectivity doesn’t need any of this — the .NET SDK caches the license on disk and validates it offline for as long as the offline-grace policy allows. This page is for machines that never connect: activation and lease renewal travel as files.
Everything rests on one trust anchor: license artifacts are signed with the provider’s key, and the device verifies them with the public key you shipped — no network required, nothing secret on the device.
How it works
Section titled “How it works”- On the device — the SDK writes an activation request file (activation code, fingerprint, application info).
- Carry it out — USB stick, one-way transfer, whatever your site allows.
- In the portal — an operator uploads the request under Offline activation; the server runs the normal activation pipeline and returns a signed response file.
- Carry it back — return the response file to the device.
- On the device — the SDK imports the response, verifies the signature and installs the license.
Add-on package: Revenusion.MonetizeIt.Client.OfflineStore (alongside
Client.LicenseConsumer).
Build the request on the device
Section titled “Build the request on the device”using Revenusion.MonetizeIt.Client.OfflineStore;
var request = new OfflineActivationRequestBuilder() .WithActivationCode("ABC123-DEF456-GHI789") .WithFingerprint(nodeIdProvider) .WithApplicationInfo(applicationInfoProvider) .Build();
await OfflineActivationRequestWriter.WriteToFileAsync(request, @"D:\transfer\activation-request.json");The fingerprint provider is the same one the online flow uses — including per-component hashes, which ride along in the request.
Issue the response
Section titled “Issue the response”In the portal, open Offline activation, upload the request file, and download
the signed response. From your own backend, the same operation is
POST /api/v1/provision/admin/activations/offline/issue.
Submitting the same request twice returns the same signed bytes — an operator double-click can’t consume a second seat.
Import on the device
Section titled “Import on the device”var importer = new OfflineActivationResponseImporterBuilder() .WithLicenseStore(licenseStore) .WithPublicKeyProvider(publicKeyProvider) .WithLicenseService(licenseService) // optional: refreshes the in-memory cache too .Build();
var result = await importer.ImportAsync(@"D:\transfer\activation-response.json");if (!result.Success) throw new InvalidOperationException(result.Message);The importer verifies the envelope signature against the pinned public key before touching the license store. From here the application runs exactly as if it had activated online.
The usage and lease loop
Section titled “The usage and lease loop”Air-gapped machines accumulate usage locally (FileTransactionStore).
Periodically, swap files again to upload usage and renew the lease:
-
Export on the device:
var exporter = new LicenseZipFileExporter(@"D:\transfer\usage-export.zip", licenseStore, transactionStore);await exporter.ExportAsync(); -
Upload in the portal — Offline activation → Ingest transactions — and download the signed receipt. (API:
POST /api/v1/provision/admin/usage/offline/ingest.) The server records the usage, extends the lease, and wraps a refreshed license in the receipt. -
Import the receipt on the device:
var importer = new OfflineTransactionReceiptImporterBuilder().WithTransactionStore(transactionStore).WithPublicKeyProvider(publicKeyProvider).WithLicenseService(licenseService).Build();var result = await importer.ImportAsync(@"D:\transfer\usage-receipt.json");On success the refreshed license is installed first, then the uploaded transactions are purged from the local log — if anything fails before the purge, the log stays intact for retry.
Repeat the swap on whatever cadence the entitlement’s lease window requires, and an air-gapped fleet stays licensed and metered indefinitely.
Operational notes
Section titled “Operational notes”- The whole loop is operator-driven through the portal in this release — there is no end-user self-service for offline activation.
- The request file is not secret (it contains hashes, not raw device traits), but treat response and receipt files as license material: they’re single-purpose, device-bound, and verified by signature on import.