Install
The C++ SDK licenses native desktop apps, games, CLI tools, Unreal Engine projects, and JUCE audio plugins. It has a header-only core with zero dependencies and verifies licenses identically to the Swift, Rust, and JavaScript SDKs (proven by cross-SDK conformance vectors). Requires C++17 or later.
Install
Section titled “Install”CMake — FetchContent (recommended)
Section titled “CMake — FetchContent (recommended)”include(FetchContent)FetchContent_Declare( keylight GIT_REPOSITORY https://github.com/keylight-dev/keylight-cpp.git GIT_TAG v0.1.0)FetchContent_MakeAvailable(keylight)
# Link against the header-only core (zero dependencies):target_link_libraries(MyApp PRIVATE keylight::keylight)
# Optional: enable the built-in HTTPS transport (needs cpp-httplib + OpenSSL):# set(KEYLIGHT_BUILD_HTTPLIB_TRANSPORT ON)# target_link_libraries(MyApp PRIVATE keylight::httplib_transport)Single-header drop-in
Section titled “Single-header drop-in”Download keylight_single.hpp from the v0.1.0 GitHub Release and place it anywhere on your include path. No CMake required — add #include "keylight_single.hpp" and you’re done.
vcpkg install keylight[httplib-transport]conan install --requires="keylight/0.1.0"Transport
Section titled “Transport”The core is network-agnostic. Supply any transport that satisfies the one-method concept (get(url) -> std::string). The opt-in HttplibTransport wraps cpp-httplib + OpenSSL:
set(KEYLIGHT_BUILD_HTTPLIB_TRANSPORT ON) # enable before FetchContent_MakeAvailable#include <keylight/httplib_transport.hpp>keylight::HttplibTransport transport;Bring your own transport by subclassing keylight::Transport — useful when you already have a network layer (e.g. FHttpModule in Unreal, juce::URL in JUCE).
Initialise
Section titled “Initialise”Fetch the tenant’s trusted keyset once so leases verify offline, then construct the client:
#include <keylight/keylight.hpp>#include <keylight/httplib_transport.hpp>
// 1. Fetch the trusted Ed25519 keyset (or pin keys in Config directly).keylight::HttplibTransport transport;auto keys = keylight::fetchKeyset(transport, "https://api.keylight.dev", "your-tenant");
// 2. Configure the client.keylight::Config cfg;cfg.tenantId = "your-tenant";cfg.productId = "your-product";cfg.sdkKey = "sdk_live_…"; // from your Keylight dashboardcfg.trustedKeys = keys.value_or(std::map<std::string, std::string>{});cfg.maxOfflineDays = 7; // optional offline grace window
// 3. Resolve the default lease store path and construct.auto storePath = keylight::default_store_path(cfg);keylight::FileStore store(storePath);keylight::Client kl(cfg, transport, store);
// 4. Run the on-launch check (validates online if needed, falls back to cached lease).kl.checkOnLaunch();Activate and gate features
Section titled “Activate and gate features”// Activate a license key (online). The returned lease is Ed25519-verified// before anything is persisted.auto res = kl.activate("USER-LICENSE-KEY");if (!res.activated) { // res.error contains the reason}
// Gate features on entitlements — works offline from the cached lease.if (kl.hasEntitlement("pro")) { // unlock pro features}
// Check the current license state.switch (kl.state()) { case keylight::State::Licensed: break; case keylight::State::Trial: break; case keylight::State::Expired: break; case keylight::State::Invalid: break;}
// Release the seat when uninstalling / switching machines.kl.deactivate();Unreal Engine
Section titled “Unreal Engine”The SDK ships a first-party Unreal adapter built on FHttpModule. Add keylight-cpp as a third-party module and use UKeylightSubsystem:
// In your GameInstance / GameMode (game thread):if (auto* KL = GetGameInstance()->GetSubsystem<UKeylightSubsystem>()){ TMap<FString, FString> TrustedKeys; TrustedKeys.Add(TEXT("k1"), TEXT("<base64-public-key>")); KL->Configure(TEXT("your-tenant"), TEXT("your-game"), TrustedKeys);
// OnActivateComplete fires on the game thread: (bSuccess, State, Message). KL->OnActivateComplete.AddDynamic(this, &AYourClass::OnActivated); KL->Activate(LicenseKey);}
// Mark UFUNCTION() in your header so AddDynamic can bind it:void AYourClass::OnActivated(bool bSuccess, EKeylightState State, const FString& Message){ if (State == EKeylightState::Licensed) { /* unlock pro content */ }}UKeylightSubsystem routes all HTTP through FHttpModule — no third-party HTTP dependency needed. Activation runs on a background thread and the completion delegate is marshaled back to the game thread.
JUCE audio plugins
Section titled “JUCE audio plugins”The SDK ships a JUCE adapter over juce::URL. The adapter is audio-thread-safe: network calls happen on a background thread; entitlement reads are lock-free via a std::atomic-backed cache.
// In your PluginProcessor (message thread):keylight::juce_integration::Licensing licensing(cfg); // uses juce::URL transportlicensing.checkOnLaunch(); // async, non-blocking
// On the audio thread (safe — lock-free atomic read):bool isPro = licensing.hasFeature("pro");Use the single-header drop-in to keep your plugin build self-contained: no CMake, no extra submodule, one #include.
- Offline verification — verify a signed lease with no network round-trip.
- GitHub · v0.1.0 Release