What you will do
Save one complete file and run it. It also supports later validate, check and deactivate actions. Keep this file through Stages 8–13.
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
cURL / REST clients
Use the cURL transport flow in the install stage, then the selected REST project's activation command. It is not an official SDK; do not grant access until signature and semantic checks pass. Browse all REST projects.
Expected result
For a valid fresh activation, standard output is exactly:
Sandbox license verified.
The program exits with code 0. In the dashboard, open [Devices](/docs/v1/start/glossary#device) or the license's Devices count: one installation is active. The sample never prints a token or full key.
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. |
Stage checklist
- My chosen sample ran against Sandbox.
- I checked the active device in the dashboard.
- I did not unlock features on an unverified answer.
Next steps
Continue to Stage 8: Validate when your app starts
You are here: Stage 7 of 14.