C++ SDK: Getting Started
C++ SDK: Getting Started
Section titled “C++ SDK: Getting Started”The Aureva C++ SDK is a public, standalone, permissively licensed library. You download it from the SDK GitHub release, drop it into your project, embed your application config, fill in a single constructor call plus init(), build for your target architecture, and call init() then license() then check().
This guide walks that integration end to end, in order.
What you download
Section titled “What you download”The SDK release mirrors the layout of a typical C++ example distribution:
| File | Purpose |
|---|---|
include/aureva/aureva.hpp | The only public header — declares aureva::Api, response, and user_data_t |
include/aureva/version.hpp | AUREVA_SDK_VERSION* macros and aureva::sdk_version() |
lib/x64/aureva_x64.lib | Prebuilt static library for x64 |
lib/x86/aureva_x86.lib | Prebuilt static library for x86 |
example/main.cpp | A minimal working integration |
example/aureva_app_config.h | A placeholder config header (replace with your generated one) |
README.md / LICENSE | Docs and the permissive license |
Step 1 — Download the SDK
Section titled “Step 1 — Download the SDK”Obtain the SDK from its GitHub release (the same surface linked from your dashboard’s per-application integration tab). Each release is a tagged, semantically versioned build with the prebuilt per-architecture libraries and the public header(s) attached as downloadable assets, so you can pin a known-good build without compiling from source.
You can confirm which build you linked at runtime:
#include <aureva/aureva.hpp>#include <cstdio>
std::printf("Aureva SDK %s\n", aureva::sdk_version()); // e.g. "1.0.0"Step 2 — Drop it into your project
Section titled “Step 2 — Drop it into your project”Place the header on your include path and link the static library for the architecture you build:
- Add
include/to your compiler’s include directories so#include <aureva/aureva.hpp>resolves. - Link
aureva_x64.libfor an x64 build, oraureva_x86.libfor an x86 build.
That is the entire footprint of the SDK in your build — one header to include and one static library to link.
Step 3 — Embed aureva_app_config.h
Section titled “Step 3 — Embed aureva_app_config.h”Your application’s secret values are not passed as plain strings in your source. They are generated for you, already encrypted, by the dashboard’s Application management area, which emits a C++ header named aureva_app_config.h. Drop that generated header onto your include path and rebuild.
The header carries five compile-time values:
| Value | What it is |
|---|---|
scriptId | The application identifier |
pk | The project main key, in its server-encrypted, embeddable form |
sk1 | Project secret key 1, server-encrypted |
sk2 | Project secret key 2, server-encrypted |
| client version | The version string the SDK reports on every init request |
If you build the SDK standalone without a generated header, it falls back to a built-in placeholder config. The placeholder values are clearly marked and non-functional by design: the SDK reports them as unconfigured and fails closed, so a placeholder build can never authenticate against the live backend. Replace the placeholder header with your generated one before shipping.
A placeholder header looks like this (illustrative — not real keys):
// aureva_app_config.h — PLACEHOLDER VALUES ONLY. Replace with the header// generated for your application by the Aureva dashboard. Never commit real keys.namespace aureva_cfg_embed { inline auto ScriptId() { return OBF("AUREVA_SCRIPT_ID_PLACEHOLDER"); } inline auto ProjectMainKey() { return OBF("AUREVA_PK_ENCRYPTED_BLOB_PLACEHOLDER"); } inline auto ProjectSecretKey1() { return OBF("AUREVA_SK1_ENCRYPTED_BLOB_PLACEHOLDER"); } inline auto ProjectSecretKey2() { return OBF("AUREVA_SK2_ENCRYPTED_BLOB_PLACEHOLDER"); } inline auto ClientVersion() { return OBF("1.0"); }}Step 4 — Fill in the minimal setup
Section titled “Step 4 — Fill in the minimal setup”The public surface is a small, familiar application object, aureva::Api. The minimal setup is a single constructor call taking the four application-secret values, plus an explicit init(). The base URL is optional and defaults to https://api.aureva.cc.
#include <aureva/aureva.hpp>
// Construct from your application secret. The values come from the encrypted,// obfuscated forms in your generated aureva_app_config.h — never raw keys.aureva::Api app( OBF("AUREVA_SCRIPT_ID"), // scriptId (compile-time obfuscated, placeholder) OBF("AUREVA_PK_ENCRYPTED_BLOB"), // pk (server-encrypted, placeholder) OBF("AUREVA_SK1_ENCRYPTED_BLOB"), // sk1 (placeholder) OBF("AUREVA_SK2_ENCRYPTED_BLOB") // sk2 (URL omitted => defaults to api.aureva.cc));Step 5 — Build for your target architecture
Section titled “Step 5 — Build for your target architecture”The SDK builds with CMake using the standard generator-platform mechanism. Run the configure step then the build step for each architecture. The static library lands in the documented output location below.
x64 (Release) — produces build/x64/Release/aureva_x64.lib:
cmake -S . -B build/x64 -G "Visual Studio 17 2022" -A x64cmake --build build/x64 --config Releasex86 (Release) — produces build/x86/Release/aureva_x86.lib:
cmake -S . -B build/x86 -G "Visual Studio 17 2022" -A Win32cmake --build build/x86 --config ReleaseThe Visual Studio generator is multi-config, so the configuration is selected at build time. Swap --config Release for --config Debug to produce the debug build; the Release configuration is the one published as the SDK release.
The CMake build links only the Win32 import libraries the SDK requires (for example winhttp, bcrypt, crypt32) and introduces no host-application dependency. This build is independent of any consuming application’s own build.
Step 6 — Call init(), then license(), then check()
Section titled “Step 6 — Call init(), then license(), then check()”Authentication runs in three calls, always in this order. Each call updates app.response before it returns — read app.response.success after each one.
#include <aureva/aureva.hpp>#include <chrono>#include <thread>
int main() { aureva::Api app( OBF("AUREVA_SCRIPT_ID"), // placeholder — use your generated config OBF("AUREVA_PK_ENCRYPTED_BLOB"), OBF("AUREVA_SK1_ENCRYPTED_BLOB"), OBF("AUREVA_SK2_ENCRYPTED_BLOB") );
// 1) init(): local integrity self-tests only. NO network, NO activation. app.init(); if (!app.response.success) { // Fail closed: do not proceed. return 1; }
// 2) license(key): activate with the user's key (init -> verify-alive). app.license(userEnteredKey); if (!app.response.success) { // Fail closed: activation denied (bad key, transport failure, // version too old, etc.). app.response.message says why (non-secret). return 1; }
// Authorized. Read entitlement / session info from user_data. const auto& u = app.user_data; // u.hwid, u.ip, u.tier, u.premium, u.expiry / u.expires_at
// 3) check(): validate the live session at a fixed interval (<= 60s), // without re-entering the key. Act on a failed result. for (;;) { std::this_thread::sleep_for(std::chrono::seconds(30)); app.check(); if (!app.response.success) { // Session no longer authorized (kick, integrity failure, etc.). // Stop permitting gated features before the next check. break; } } return 0;}What each call does:
init()runs the SDK’s native integrity self-tests. It performs no network operation and no activation.successistrueonly if every self-test passes.license(key)trims the key and runs the activation flow (init request → verify-alive) within its timeout.successistrueonly when both stages authorize. An empty or all-whitespace key fails closed with no network operation.check()validates the live session via the heartbeat / verify-alive flow without re-entering the key.successtracks whether the session is still authorized. Call it at a fixed interval of no more than 60 seconds and act on a failed result.
The success / message fail-closed contract
Section titled “The success / message fail-closed contract”Every public call updates the response struct before returning:
struct response { bool success; // outcome of the most recent call std::string message; // non-empty, non-secret when success == false};The contract you rely on:
- Check
successafterinit()and afterlicense()before doing anything that depends on authorization. This is the fail-closed usage pattern — treat anything other thansuccess == trueas denied. - When
successisfalse,messageis a non-empty, non-secret diagnostic explaining the cause. It never contains key or secret material. - Calls made out of order fail closed:
license()before a successfulinit(),check()before a successfullicense(), orlicense()with a blank key all setsuccess = false, perform no network operation, and never report the session as authorized. - Any transport failure, timeout, or backend denial sets
success = falsewith a non-secretmessageand drives the SDK’s denial path.
Thread-safety
Section titled “Thread-safety”A single aureva::Api instance is used from one thread at a time for the mutating calls init() / license() / check(). Reading app.response and app.user_data from a different thread (for example a UI or render thread) is safe and non-blocking. For full details, see C++ SDK: Thread-Safety Contract.
Next steps
Section titled “Next steps”- Auth Flow & Error Surfaces — the heavy C++ flow vs the lightweight Luau loader, and how the error surfaces relate
- Thread-Safety Contract — concurrency rules for embedding the SDK
- SDK Overview — the multi-client model