What you will build
A small Sandbox program that activates a key and checks the server's signed decision before reporting access. Plan for about ten minutes after email and runtime setup; installation and email delivery can take longer.
What you need
An inbox you control, an internet connection and one of the runtimes listed below. No account or licensing knowledge is assumed. Use a user-owned example folder and private state directory.
1. Create your Sandbox workspace
- Open registration and select Free for Sandbox evaluation.
- Enter an email you control and verify the code or single-use link from the message.
- Complete your name, workspace name, password and terms acknowledgement.
- In the workspace header, select Sandbox.
A workspace is the private area that contains your products and licenses. Sandbox means test records, separate from Live. A paid platform selection can require checkout; it is not a customer license purchase.
2. Create your product and plan
- Open Products → New product (or Create product on an empty page).
- Enter Product name Quickstart App, Slug quickstart-app, Platform Desktop, and License prefix QUICK. Choose Create product.
- Saving opens the first-plan form in Plans & [features](/docs/v1/start/glossary#feature). If it is closed, choose New plan.
- Select Quickstart App. Enter Plan name Quickstart plan and Slug quickstart-plan.
- Choose Currency EUR, Price 19.50, Billing type Monthly, Duration days 30, Max [devices](/docs/v1/start/glossary#device) 2 and Feature keys pdf_export.
- Choose Create plan. Return to Products and copy the product's public App ID.
A product represents your software. Its App ID is the application identifier; there is no separate Application record to create. A plan describes access for that product. These plan prices are reference metadata, not a payment or recurring charge.
3. Issue your test key
- Open Licenses while the header still says Sandbox.
- Choose New license or Create first license.
- Select Quickstart App / Quickstart plan in Product and plan.
- Enter your test Customer email and a simple Customer name, such as Quickstart Tester. Company and External customer ID are optional.
- Choose Create license. Copy Your new [license key](/docs/v1/start/glossary#license-key), shown once, into your private test configuration.
The dashboard creates or reuses the customer for this email. A new license has no activated devices yet.
4. Install your chosen SDK
Python
Python setup
Use Python 3.11–3.14 and a working HTTPS certificate store. The official package is published on PyPI with GitHub source. Create a virtual environment, then install:
python3 -m venv .venv
.venv/bin/python -m pip install "kdpika-licensing==1.1.5"
.venv/bin/python -m pip check
On native Windows use py -m venv .venv, then .venv\\Scripts\\python.exe for both pip commands and the example. Import kdpika_licensing. Use the same virtualenv interpreter for pip and your example.
JavaScript / Node.js
JavaScript setup
Requires Node.js 18+ source compatibility, npm and an authenticated backend, CLI or Electron main process. Do not run this SDK in a web page. Download JavaScript SDK 1.0.0 and extract into kdpika-javascript-sdk, then run:
npm install --ignore-scripts --save-exact ./kdpika-javascript-sdk
Save your example with the .mjs extension. The installed module is @kdpika/license-sdk. Choose a maintained Node runtime for production and run the compatibility tests there.
PHP
PHP setup
Requires PHP 8.2+, cURL, Sodium and Composer. The package's older ^8.1 declaration is not its actual minimum. Download PHP SDK 1.0.0 and extract into kdpika-php-sdk:
composer install --working-dir ./kdpika-php-sdk --no-interaction --no-plugins --no-scripts --prefer-dist
The example loads that folder's vendor/autoload.php. It runs on your trusted backend or CLI, not in browser JavaScript. KDP_SDK_DIR can point to a different extracted package folder.
C# / .NET
C# setup
Requires the .NET SDK and the unchanged SDK's net7.0 source target. Download C# SDK 1.0.0 and extract into kdpika-csharp-sdk. Save the project below beside that folder:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems></PropertyGroup>
<ItemGroup><Compile Include="Program.cs"/>
<ProjectReference Include="kdpika-csharp-sdk/KDPika.LicenseSdk/KDPika.LicenseSdk.csproj"/>
</ItemGroup>
</Project>
dotnet restore Guide.csproj
The demonstrated net7 target is an existing compatibility constraint, not a recommendation to deploy an end-of-support runtime. Production needs a maintained-runtime compatibility assessment; see the disclosed SDK limitations.
cURL / other language
cURL setup
This is a transport exercise, not an SDK or signature verifier. Use this route for a REST-only language, then follow its real client and verification project before granting access.
umask 077
curl --fail --silent --show-error -o response-private.json \
-H "X-App-ID: $KDP_APP_ID" -H "X-Environment: SANDBOX" \
-H "Content-Type: application/json" \
--data '{"license_key":"YOUR_SANDBOX_LICENSE_KEY","device_id":"guide-install-CHANGE-ONCE"}' \
https://licensing.kdpika.com/api/v1/licenses/activate
Replace the key privately. Keep the device_id stable for this installation. The file contains a private activation token: do not publish or log it. HTTP success alone does not authorize your app. Read activation, then choose your REST client and signature verification.
5. Configure your terminal
Set these variables in your terminal. App ID is public; your customer's key and state directory are private. Do not use a developer API key in this client.
macOS / Linux · Bash
export KDP_APP_ID="YOUR_PUBLIC_APP_ID"
export KDP_CUSTOMER_EMAIL="YOUR_TEST_CUSTOMER_EMAIL"
export KDP_STATE_DIR="$HOME/.kdpika-guide-sandbox"
read -r -s -p "Sandbox license key: " KDP_LICENSE_KEY
printf '\n'
export KDP_LICENSE_KEY
For a different device test, use a new private state directory, not a different email.
Windows · PowerShell
$env:KDP_APP_ID = "YOUR_PUBLIC_APP_ID"
$env:KDP_CUSTOMER_EMAIL = "YOUR_TEST_CUSTOMER_EMAIL"
$env:KDP_STATE_DIR = Join-Path $env:LOCALAPPDATA "KDPikaGuideSandbox"
$secureKey = Read-Host "Sandbox license key" -AsSecureString
$env:KDP_LICENSE_KEY = [System.Net.NetworkCredential]::new("", $secureKey).Password
The variable is plaintext in this process; do not print it or leave it in a shared terminal. Close the terminal after testing. Windows Python uses .venv\\Scripts\\python.exe; Node/PHP/.NET commands are the same if their runtimes are installed.
Expected result: the variables are available only to this terminal and its child processes. Use a user-owned directory, outside a web root or shared repository. The sample uses Sandbox explicitly.
6. Save and run one complete file
Python
Save license-check.py in your example folder.
"""Sandbox learning example; use private state, never a developer API key."""
import os
import sys
from pathlib import Path
from kdpika_licensing import LicenseClient
try:
action = sys.argv[1] if len(sys.argv) == 2 else "activate"
if action not in ("activate", "validate", "check", "deactivate"):
raise ValueError("Choose an action")
client = LicenseClient(
product=os.environ["KDP_APP_ID"], environment="SANDBOX",
base_url=os.getenv("KDP_BASE_URL", "https://licensing.kdpika.com"),
storage_dir=Path(os.environ["KDP_STATE_DIR"]), prefer_keyring=False)
result = client.activate(os.environ["KDP_LICENSE_KEY"],
os.getenv("KDP_CUSTOMER_EMAIL") or None) if action == "activate" else getattr(client, action)()
released = action == "deactivate" and result.valid
allowed = action != "deactivate" and result.valid and result.signature_valid
print("Device released." if released else "Sandbox license verified." if allowed
else "License could not be confirmed. Check your key or contact support.")
sys.exit(0 if released or allowed else 1)
except Exception:
print("License check unavailable. Check configuration and connection.", file=sys.stderr)
sys.exit(2)
Run:
.venv/bin/python license-check.py activate
JavaScript / Node.js
Save license-check.mjs in your example folder.
// Node.js / Electron main process, not browser JavaScript.
import { LicenseClient } from '@kdpika/license-sdk';
try {
const action = process.argv[2] || 'activate';
if (!['activate', 'validate', 'check', 'deactivate'].includes(action)) throw Error();
const client = new LicenseClient({
product: process.env.KDP_APP_ID, environment: 'SANDBOX',
baseUrl: process.env.KDP_BASE_URL || 'https://licensing.kdpika.com',
storageDir: process.env.KDP_STATE_DIR
});
if (!process.env.KDP_STATE_DIR) throw Error();
const result = action === 'activate'
? await client.activate(process.env.KDP_LICENSE_KEY, process.env.KDP_CUSTOMER_EMAIL || null)
: await client[action]();
const released = action === 'deactivate' && result.valid;
const allowed = action !== 'deactivate' && result.valid && result.signatureValid;
console.log(released ? 'Device released.' : allowed ? 'Sandbox license verified.'
: 'License could not be confirmed. Check your key or contact support.');
process.exitCode = released || allowed ? 0 : 1;
} catch {
console.error('License check unavailable. Check configuration and connection.');
process.exitCode = 2;
}
Run:
node license-check.mjs activate
PHP
Save license-check.php in your example folder.
<?php
declare(strict_types=1);
use KDPika\LicenseSdk\LicenseClient;
try {
require (getenv('KDP_SDK_DIR') ?: './kdpika-php-sdk').'/vendor/autoload.php';
$action = $argv[1] ?? 'activate';
if (!in_array($action, ['activate','validate','check','deactivate'], true)
|| !getenv('KDP_APP_ID') || !getenv('KDP_STATE_DIR')) throw new RuntimeException();
$client = new LicenseClient(product:getenv('KDP_APP_ID'), environment:'SANDBOX',
baseUrl:getenv('KDP_BASE_URL') ?: 'https://licensing.kdpika.com',
storageDir:getenv('KDP_STATE_DIR'));
$result = $action === 'activate'
? $client->activate(getenv('KDP_LICENSE_KEY') ?: '', getenv('KDP_CUSTOMER_EMAIL') ?: null)
: $client->$action();
$released = $action === 'deactivate' && $result->valid;
$allowed = $action !== 'deactivate' && $result->valid && $result->signatureValid;
echo $released ? 'Device released.' : ($allowed ? 'Sandbox license verified.'
: 'License could not be confirmed. Check your key or contact support.'), PHP_EOL;
exit($released || $allowed ? 0 : 1);
} catch (Throwable) {
fwrite(STDERR, 'License check unavailable. Check configuration and connection.'.PHP_EOL);
exit(2);
}
Run:
php license-check.php activate
C# / .NET
Save Program.cs in your example folder.
using KDPika.LicenseSdk;
static string Required(string name) => Environment.GetEnvironmentVariable(name)
is string value && value.Length > 0 ? value : throw new ArgumentException();
try {
var action = args.Length == 0 ? "activate" : args[0];
if (!new[]{"activate","validate","check","deactivate"}.Contains(action)) throw new ArgumentException();
var client = new LicenseClient(Required("KDP_APP_ID"), "SANDBOX",
Environment.GetEnvironmentVariable("KDP_BASE_URL") ?? "https://licensing.kdpika.com",
storageDir:Required("KDP_STATE_DIR"));
var result = action switch {
"activate" => await client.ActivateAsync(Required("KDP_LICENSE_KEY"),
Environment.GetEnvironmentVariable("KDP_CUSTOMER_EMAIL")),
"validate" => await client.ValidateAsync(), "check" => await client.CheckAsync(),
_ => await client.DeactivateAsync()
};
var released = action == "deactivate" && result.Valid;
var allowed = action != "deactivate" && result.Valid && result.SignatureValid;
Console.WriteLine(released ? "Device released." : allowed ? "Sandbox license verified."
: "License could not be confirmed. Check your key or contact support.");
Environment.ExitCode = released || allowed ? 0 : 1;
} catch {
Console.Error.WriteLine("License check unavailable. Check configuration and connection.");
Environment.ExitCode = 2;
}
Run:
dotnet run --project Guide.csproj -- activate
Expected result
The chosen official SDK sample prints exactly:
Sandbox license verified.
It exits with code 0 and the dashboard's Devices count shows one active installation. No real charge is made. A cURL-only success is a transport result, not a verified access grant.
If it does not work
| What you see | What to do |
|---|---|
| INVALID_LICENSE | Check the full key, public App ID, Sandbox selection and matching customer email. |
| MAX_DEVICES_REACHED | Deactivate an old installation or inspect Devices. Do not make random identities. |
| SIGNATURE_INVALID / cached signature error | Keep access locked. Check the runtime, clock and SDK compatibility notes; do not disable verification. |
| NOT_ACTIVATED | Run activate in the same private state directory first. |
| NETWORK_ERROR / no connection | Reconnect. A first activation needs internet; no cached response means no offline grant. |
| LICENSE_EXPIRED / LICENSE_REVOKED / LICENSE_SUSPENDED | Explain the state to the customer and provide support; never silently convert it to valid. |
Next steps
Previous detailed reference
The earlier quickstart reference retains all earlier explanations and example files. It is supplementary, not required for this page.