Quickstart: C++
This quickstart takes about ten minutes. You activate a license from C++, persist it to disk, confirm it validates with no network connection, and release the seat again.
Before you start
From Getting started you should have your vendor id (console → Settings), a license key (issued by an order, Orders → Create, and emailed to the customer), and the installed SDK.
Project setup
The SDK ships a CMake package. The C++ surface consists of header-only wrapper classes, so there is nothing else to link against:
find_package(sws CONFIG REQUIRED)
target_link_libraries(your_app PRIVATE sws::sws)
The whole program
This is a complete, runnable integration: the same loop your application runs on every start.
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include "softactivate/sws_licensing.h"
// load a previously saved license, if any - after the first (online) activation,
// every later start validates this file with no network access at all
static std::unique_ptr<sws::licensing::license> load_license()
{
std::ifstream file("license.dat");
if (!file)
return nullptr;
std::stringstream buffer;
buffer << file.rdbuf();
return std::make_unique<sws::licensing::license>(buffer.str().c_str());
}
int main()
{
try
{
auto client = sws::licensing::client::create("https://lm.sws.softactivate.com");
client->set_metadata("trusted_domain", "sws.softactivate.com");
// your tenant coordinates - vendor id from the console (Settings),
// license key from your order's delivery email
client->set_vendor_id("YOUR-VENDOR-ID");
client->set_license_key("XXXXX-XXXXX-XXXXX-XXXXX-XXXXX");
// your product's Reference Id (console -> Products): a key for a
// different product is refused - see the product binding guide
client->set_product_id("YOUR_PRODUCT_ID");
// validate: with no stored license this activates the device (online, once);
// with a stored license it verifies the certificate chain, the device
// fingerprint and the dates locally - and renews online only when needed
auto params = client->create_license_validation_params();
auto license = load_license();
if (license)
params->set_license(license);
auto result = client->validate_license(params);
if (!result->is_license_valid())
{
// the precise status says WHY - expired, revoked, bound to another
// machine, subscription lapsed... each deserves different UX; see the
// statuses reference: /licensing/docs/status-codes/
std::cerr << "License is not valid (status " << result->get_status() << ")\n";
return 1;
}
// persist the new or renewed certificate whenever one is issued
if (auto updated = result->get_updated_license())
std::ofstream("license.dat") << updated->serialize();
std::cout << "License is valid.\n";
return 0;
}
catch (const std::exception& ex)
{
std::cerr << "Licensing error: " << ex.what() << "\n";
return 1;
}
}
Replace the vendor id and license key with yours, put deployment-root.crt next to the
binary (in your real product, embed it or install it with your application), and run
it.
Run it three times
- First run (online): no
license.datexists, sovalidate_licenseactivates the device with the service. The SDK receives the license and the program saves it tolicense.dat. - Second run (disconnect the network if you like): the stored license is verified entirely on the machine, and no network access happens. This is the everyday path your customers' machines take on every start.
- Moving on: when you are done with this machine, release its seat so the key can activate elsewhere:
client->deactivate_license();
std::remove("license.dat"); // the local file is now meaningless
When validation says no
A false result from is_license_valid() can mean several different things.
get_status() tells you whether the license is expired, revoked, bound to a different
device, or waiting on a lapsed subscription, and each case deserves different UX. The
statuses and errors reference maps every status to a
recommended action.
If your codebase is C rather than C++, the headers also expose the underlying interface
directly: sws_* structs and the sws_licensing_client_create factory function. The
wrapper classes are optional if your integration layer prefers working at that level.
Next: the .NET quickstart, or go deeper on getting started in the console.