/ examples

Real code. Copy and ship.

End-to-end examples for every key type — from Roblox game scripts to Node.js API middleware. Each snippet is production-ready and wired to the live API.

script surface

Script key system

Roblox executors, game scripts, Lua tools

Script keys work with HWID binding and optional ad checkpoints. The first time a device validates, its hardware ID is stored — subsequent attempts from other machines get hwid_mismatch.

1. Generate keys (your server / Discord bot)

Always mint keys server-side — never expose your API secret in game scripts.

const res = await fetch("https://keysystem.nabzclan.vip/api/v1/keys/generate", {
  method: "POST",
  headers: {
    "x-project": "p_YOUR_PROJECT_ID",
    "Authorization": "Bearer YOUR_API_SECRET",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    count: 10,
    label: "discord-giveaway-june",
    ttl_minutes: 10080, // 7 days
  }),
});
const { keys } = await res.json();
// keys[0].key => "KS-XXXX-XXXX-XXXX"
console.log(keys.map(k => k.key).join("\n"));

2. Complete a checkpoint (Lua, Roblox)

If your project has checkpoints enabled, the player must complete each step before validation succeeds. Use the checkpoint slug — not its ID.

local HttpService = game:GetService("HttpService")
local PROJECT_ID = "p_YOUR_PROJECT_ID"

local function completeCheckpoint(key: string, checkpointSlug: string)
    local ok, result = pcall(function()
        local response = HttpService:RequestAsync({
            Url = "https://keysystem.nabzclan.vip/api/v1/checkpoints/complete",
            Method = "POST",
            Headers = {
                ["Content-Type"] = "application/json",
                ["x-project"] = PROJECT_ID,
            },
            Body = HttpService:JSONEncode({
                key = key,
                checkpoint = checkpointSlug,
            }),
        })
        return HttpService:JSONDecode(response.Body)
    end)

    if not ok then return false, "Network error" end
    if result.cleared then
        return true, "All checkpoints done!"
    end
    return false, result.remaining .. " checkpoint(s) remaining"
end

-- After the player clicks the ad/link button:
local done, msg = completeCheckpoint("KS-7H2P-VLNX-9KJ4", "step-1-linkvertise")
print(msg)

3. Validate key with HWID (Lua, Roblox)

The first validate call with a new HWID binds the key to that device. Subsequent calls from different HWIDs are rejected.

local HttpService = game:GetService("HttpService")
local PROJECT_ID = "p_YOUR_PROJECT_ID"

local REASONS = {
    checkpoints_required = function(data)
        return "Complete " .. (data.checkpoints_remaining or 1) .. " step(s) first"
    end,
    hwid_mismatch  = "Key is bound to another device",
    hwid_required  = "Key requires a device ID",
    expired        = "Key has expired",
    revoked        = "Key has been revoked",
    paused         = "Key is temporarily paused",
    invalid_key    = "Key not found",
}

local function validateKey(key: string): (boolean, string?)
    -- Use a stable fingerprint — RbxAnalyticsService or a saved GUID
    local hwid = game:GetService("RbxAnalyticsService"):GetClientId()

    local ok, resp = pcall(HttpService.RequestAsync, HttpService, {
        Url    = "https://keysystem.nabzclan.vip/api/v1/keys/validate",
        Method = "POST",
        Headers = {
            ["Content-Type"] = "application/json",
            ["x-project"]    = PROJECT_ID,
        },
        Body = HttpService:JSONEncode({ key = key, hwid = hwid }),
    })

    if not ok then return false, "Network error — try again" end

    local data = HttpService:JSONDecode(resp.Body)
    if data.valid then return true, nil end

    local reason = REASONS[data.reason]
    if type(reason) == "function" then reason = reason(data) end
    return false, reason or ("Blocked: " .. (data.reason or "unknown"))
end

-- Usage:
local granted, err = validateKey(script.Parent.TextBox.Text)
if granted then
    game.Players.LocalPlayer.leaderstats.Access.Value = true
else
    warn("[KeySystem] " .. (err or "denied"))
end
api surface

API access key (sk_xxx)

SaaS products, developer tools, rate-limited services

API keys are prefixed sk_live_ and carry scopes and per-minute rate limits. Use them as drop-in authentication for your own API.

1. Issue a key to a customer

curl -X POST https://keysystem.nabzclan.vip/api/v1/keys/generate \
  -H "x-project: p_YOUR_PROJECT_ID" \
  -H "Authorization: Bearer YOUR_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "count": 1,
    "label": "customer-alice",
    "scopes": ["read", "write"],
    "rate_limit_per_minute": 60
  }'

# Response:
# { "ok": true, "count": 1, "keys": [
#   { "id": "k_xxx", "key": "sk_live_Dp3CEgv4...", "expires_at": null }
# ]}

2. Validate on each incoming request (Express middleware)

import type { Request, Response, NextFunction } from "express";

const PROJECT_ID = process.env.KEYSTATION_PROJECT_ID!;

// Cache validation results briefly to reduce API calls
const cache = new Map<string, { valid: boolean; scopes: string[]; exp: number }>();

async function keystationAuth(req: Request, res: Response, next: NextFunction) {
  const apiKey =
    req.headers["x-api-key"] as string ||
    req.headers.authorization?.replace(/^Bearers+/i, "");

  if (!apiKey) return res.status(401).json({ error: "Missing API key" });

  // Check local cache (10s TTL)
  const cached = cache.get(apiKey);
  if (cached && cached.exp > Date.now()) {
    if (!cached.valid) return res.status(401).json({ error: "Invalid key" });
    req.scopes = cached.scopes;
    return next();
  }

  const resp = await fetch("https://keysystem.nabzclan.vip/api/v1/keys/validate", {
    method: "POST",
    headers: { "x-project": PROJECT_ID, "Content-Type": "application/json" },
    body: JSON.stringify({ key: apiKey }),
  });

  if (resp.status === 429) return res.status(429).json({ error: "Rate limited" });

  const data = await resp.json();
  const scopes: string[] = Array.isArray(data.scopes) ? data.scopes :
    typeof data.scopes === "string" ? JSON.parse(data.scopes) : [];

  cache.set(apiKey, { valid: data.valid, scopes, exp: Date.now() + 10_000 });

  if (!data.valid) return res.status(401).json({ error: data.reason ?? "Invalid key" });

  req.scopes = scopes;
  next();
}

// Scope guard helper
function requireScope(scope: string) {
  return (req: Request, res: Response, next: NextFunction) => {
    if (!req.scopes?.includes(scope)) {
      return res.status(403).json({ error: `Missing scope: ${scope}` });
    }
    next();
  };
}

export { keystationAuth, requireScope };
license surface

Software license

Desktop apps, CLIs, Electron apps — machine-bound seats

License keys bind to machine fingerprints. Each activation consumes a seat (up to max_activations). Users can deactivate a machine to transfer a seat to another device.

1. Activate on install

import httpx, uuid, platform, sys

PROJECT_ID = "p_YOUR_PROJECT_ID"

def get_machine_id() -> str:
    """Stable fingerprint — MAC address as UUID."""
    return str(uuid.UUID(int=uuid.getnode()))

def activate(license_key: str) -> dict:
    resp = httpx.post(
        "https://keysystem.nabzclan.vip/api/v1/license/activate",
        headers={"x-project": PROJECT_ID, "Content-Type": "application/json"},
        json={
            "key": license_key,
            "machine_id": get_machine_id(),
            "machine_name": platform.node(),
        },
    )
    data = resp.json()
    if not data.get("ok"):
        print("Activation failed. Seat limit may be reached.", file=sys.stderr)
        sys.exit(1)
    print(f"✓ Activated — {data['seats_used']}/{data['seats_max']} seats used")
    return data

activate("ABCD-EFGH-IJKL-MNOP-QRST")

2. Validate on every launch

def check_license(license_key: str) -> bool:
    resp = httpx.post(
        "https://keysystem.nabzclan.vip/api/v1/keys/validate",
        headers={"x-project": PROJECT_ID, "Content-Type": "application/json"},
        json={"key": license_key, "machine_id": get_machine_id()},
    )
    data = resp.json()

    if data.get("valid"):
        return True

    reason = data.get("reason", "unknown")
    messages = {
        "activation_limit_reached": "Seat limit reached — deactivate another machine.",
        "expired": "Your license has expired. Renew at nabzclan.vip.",
        "revoked": "License revoked. Contact support.",
        "hwid_mismatch": "Machine mismatch — run on your registered device.",
    }
    print("License check failed:", messages.get(reason, reason), file=sys.stderr)
    return False

if not check_license("ABCD-EFGH-IJKL-MNOP-QRST"):
    sys.exit(1)

3. Transfer license (deactivate old machine)

def deactivate(license_key: str, machine_id: str | None = None) -> bool:
    mid = machine_id or get_machine_id()
    resp = httpx.post(
        "https://keysystem.nabzclan.vip/api/v1/license/deactivate",
        headers={"x-project": PROJECT_ID, "Content-Type": "application/json"},
        json={"key": license_key, "machine_id": mid},
    )
    data = resp.json()
    if data.get("deactivated"):
        print(f"Deactivated. {data['seats_used']}/{data['seats_max']} seats now used")
        return True
    return False

# Transfer flow:
# 1. Deactivate old machine (run on old machine, or pass its machine_id)
deactivate("ABCD-EFGH-IJKL-MNOP-QRST")
# 2. Activate on new machine
activate("ABCD-EFGH-IJKL-MNOP-QRST")
webhooks

Webhook handler

React to events in real-time — always verify the signature

Every webhook POST includes an x-keystation-signature: sha256=<hex> header. Always verify it before processing — use constant-time comparison to prevent timing attacks.

Express (Node.js)

import express from "express";
import crypto from "node:crypto";

const app = express();
// IMPORTANT: use raw body parser to get the exact bytes for HMAC
app.use("/webhooks", express.raw({ type: "application/json" }));

const WEBHOOK_SECRET = process.env.KEYSTATION_WEBHOOK_SECRET!;

function verify(rawBody: Buffer, signatureHeader: string): boolean {
  const expected = "sha256=" +
    crypto.createHmac("sha256", WEBHOOK_SECRET).update(rawBody).digest("hex");
  try {
    return crypto.timingSafeEqual(
      Buffer.from(signatureHeader),
      Buffer.from(expected),
    );
  } catch {
    return false;
  }
}

app.post("/webhooks/keystation", (req, res) => {
  const sig = req.headers["x-keystation-signature"] as string;

  if (!sig || !verify(req.body as Buffer, sig)) {
    return res.status(401).json({ error: "Signature mismatch" });
  }

  const { event, data, sent_at } = JSON.parse((req.body as Buffer).toString());

  switch (event) {
    case "key.validated":
      console.log(`Key ${data.key_id} used from ${data.ip}`);
      // update last_seen in your database
      break;

    case "key.expired":
      console.log(`Key ${data.key_id} expired`);
      // notify the user — send email or Discord DM
      break;

    case "key.activated":
      console.log(`Seat activated for key ${data.key_id} on machine ${data.machine_id}`);
      break;

    case "checkpoint.complete":
      console.log(`Checkpoint ${data.checkpoint} cleared for key ${data.key_id}`);
      break;
  }

  res.json({ ok: true });
});
obfuscator

Code obfuscator

7 languages — Lua, JS, PHP, HTML, CSS, Python, JSON

The Keystation obfuscator is a dashboard tool, not an API endpoint — it runs in your browser. Head to /dashboard/obfuscator to protect your Lua scripts, JavaScript bundles, PHP source, or other code before shipping it.

Lua

XOR string encryption, local renaming, anti-tamper checksum, loadstring wrapper

JavaScript

String array RC4/base64, control flow flattening, dead code injection, self-defending

PHP

Multi-pass eval + gzinflate + base64, str_rot13/strrev salting between passes

HTML

Minify, entity-encode text nodes, obfuscate inline scripts, base64 outer wrap

Python

Multi-pass exec + zlib.decompress + base64.b64decode

CSS

Strip comments, minify whitespace, high-strength selector rename

JSON

Low: base64 envelope. Medium/high: XOR + base64 with key in envelope

Ready to ship?

Create a project and get your API keys in 30 seconds.