Overview

KeyVault is a high-security license management system with hardware ID locking, encrypted validation, and full audit logging. It provides a RESTful API for managing and validating license keys.

Project Isolation

Separate keys by project with unique API secrets

HWID Locking

Bind keys to PC hardware IDs

AES-256-GCM

End-to-end encryption for all payloads

Anti-Replay

Server-side nonce rotation per validation

Rate Limiting

Per-IP and per-key request throttling

Audit Logs

Every action is logged with IP and HWID

Telegram Bot

Native API for Telegram bot integration

User Portal

Per-project user dashboards with customizable blocks

Portal Editor

Drag-and-drop dashboard builder for each project

No-Key Flow

Users can register without a key, add one later

HWID Gating

Restrict features until HWID is bound in loader

Admin Panel

Full admin view of all users, projects, and keys

Authentication

Admin endpoints require a Bearer token obtained via the login endpoint. Public endpoints (validate, telegram, portal) don't require admin authentication. Self-registration is disabled — only the first user (setup) and admin-created users are allowed.

POST/api/auth/login

Authenticate and receive a JWT token stored as an HTTP-only cookie.

Request Body
json
{
  "email": "admin@keyvault.io",
  "password": "your-password"
}
Response
json
{
  "success": true,
  "data": {
    "user": { "id": "...", "email": "admin@keyvault.io", "role": "ADMIN" },
    "token": "eyJhbGciOiJIUzI1NiIs..."
  }
}

💡 For programmatic access, use the Authorization: Bearer <token> header.

Projects

Projects let you organize license keys into separate namespaces. Each project gets a unique API secret (kv_...) that clients use during validation to scope keys to a specific project.

How It Works

  1. 1. Create a project in the dashboard — a unique kv_ secret is generated automatically
  2. 2. Assign keys to the project when generating them
  3. 3. In your client app, include the project's secret field in validate/heartbeat/telegram requests
  4. 4. The API will only match keys belonging to that project

💡 The secret field is optional. If omitted, validation searches across all keys regardless of project.

User Portal

Each project gets a public-facing user portal at /p/[slug]. End-users can register, activate license keys, download the loader, and view their account status — all configurable via the Portal Dashboard Editor.

User Flow

  1. 1. User visits /p/your-project-slug
  2. 2. Creates an account (no key required) or signs in
  3. 3. Enters license key to activate it on their account
  4. 4. Downloads the loader and binds HWID
  5. 5. Full access granted after HWID binding

Access Levels

No key: Limited view, can only activate a key
Key activated, no HWID: Key info visible, loader download prompt
Full access (HWID bound): All features unlocked

Portal Dashboard Editor

In project settings, use the Portal Dashboard Editor to customize which blocks appear on the user portal. Available blocks:

key_info

License status, plan, expiry, sessions

copy_key

Button to copy the license key mask

download_loader

Loader download with HWID gating

hwid_status

HWID binding status indicator

custom_button

External link (Discord, website, etc.)

custom_text

Custom paragraph of text

POST/api/portal/register

Register a portal user (no key required)

Request Body
json
{
  "username": "player123",
  "password": "securepass",
  "projectId": "clxxx..."
}
Response
json
{
  "success": true,
  "data": {
    "token": "eyJ...",
    "user": { "id": "...", "username": "player123", "projectId": "...", "keyId": null }
  }
}
POST/api/portal/login

Login as a portal user

Request Body
json
{
  "username": "player123",
  "password": "securepass",
  "projectId": "clxxx..."
}
GET/api/portal/me

Get portal user info, key data, access level, and project dashboard config. Requires portal_token cookie or Bearer token.

Response
json
{
  "success": true,
  "data": {
    "user": { "id": "...", "username": "player123" },
    "key": { "mask": "A1B2-****-****-G7H8", "plan": "MONTHLY", "status": "ACTIVE", "hwidLocked": true },
    "access": {
      "hasKey": true,
      "keyActive": true,
      "hwidBound": true,
      "fullAccess": true,
      "canDownloadLoader": true,
      "loaderUrl": "https://..."
    }
  }
}
POST/api/portal/activate

Activate a license key on portal user account. Requires portal auth.

Request Body
json
{
  "key": "A1B2-C3D4-E5F6-G7H8"
}
Response
json
{
  "success": true,
  "data": {
    "message": "Key activated successfully!",
    "key": { "mask": "A1B2-****-****-G7H8", "plan": "WEEKLY", "status": "ACTIVE" },
    "needsHwidBinding": true
  }
}
GET/api/portal/info?slug=my-project

Get public project info for portal page (no auth required)

POST/api/portal/logout

Clear portal auth cookie

API Endpoints

Complete list of available API endpoints.

POST/api/auth/login

Login and get JWT token

POST/api/auth/register

Register a new admin (first-use setup or admin-only)

POST/api/auth/logout

Clear auth cookie

GET/api/auth/me

Get current user info

GET/api/keys?projectId=xxx

List all license keys (paginated, optional project filter)

POST/api/keys

Generate new license keys

Request Body
json
{
  "plan": "WEEKLY",       // DAILY | WEEKLY | MONTHLY | LIFETIME | CUSTOM
  "count": 5,             // 1-50 keys at once
  "maxSessions": 1,       // Max concurrent sessions
  "customDays": 90,       // Required if plan is CUSTOM (1-3650)
  "note": "VIP client",   // Optional admin note
  "projectId": "clxxx..." // Optional project ID
}
GET/api/keys/:id

Get key details with recent logs

PATCH/api/keys/:id

Update key status, reset HWID, change sessions

Request Body
json
{
  "status": "BANNED",     // ACTIVE | EXPIRED | BANNED | REVOKED
  "resetHwid": true,      // Reset hardware ID lock
  "maxSessions": 3        // Update max sessions
}
DELETE/api/keys/:id

Revoke a license key

GET/api/logs

View audit logs (paginated)

GET/api/stats

Dashboard statistics

GET/api/projects

List user's projects

POST/api/projects

Create a new project (auto-generates API secret)

Request Body
json
{
  "name": "My Game",
  "description": "Game license management"
}
GET/api/projects/:id

Get project details with key count

PATCH/api/projects/:id

Update project or regenerate secret

Request Body
json
{
  "name": "New Name",
  "description": "Updated description",
  "regenerateSecret": true  // optional: generates new kv_ secret
}
DELETE/api/projects/:id

Delete project and all its keys

GET/api/heartbeat

Health check endpoint

GET/api/admin

Admin only: list all users, projects, and keys

GET/api/portal/info?slug=xxx

Public project info for portal page

POST/api/portal/register

Register a portal user (no key required)

POST/api/portal/login

Login as a portal user

GET/api/portal/me

Get portal user info, key status, and access level

POST/api/portal/activate

Activate a license key on portal user account

POST/api/portal/logout

Clear portal auth cookie

License Validation

The core endpoint for validating license keys from your application. No auth required — just send the key and hardware ID.

POST/api/validate

Validate a license key and receive server-side variables. HWID is locked on first use.

Request Body
json
{
  "key": "A1B2-C3D4-E5F6-G7H8",
  "hwid": "sha256-hash-of-hardware-id",
  "secret": "kv_abc123..."     // Project secret (optional, scopes to project)
}
Response
json
{
  "success": true,
  "data": {
    "valid": true,
    "plan": "WEEKLY",
    "expiresAt": "2026-03-07T12:00:00.000Z",
    "note": "VIP client",
    "serverVar": "encrypted-server-variable",
    "nonce": "one-time-nonce-rotated-per-call",
    "sessionId": "uuid-v4"
  }
}

HWID Generation Guide

Generate a hardware fingerprint by combining stable system identifiers. Recommended: SHA256(MotherboardUUID + ":" + DiskSerial). For Telegram bots, use the user's Telegram ID via the /api/telegram endpoint instead.

Telegram Bot Integration

A dedicated API endpoint for Telegram bots. The PC HWID is passed from the client — the bot simply forwards the key + HWID to the API and returns the result.

POST/api/telegram

Telegram bot actions: validate, info, reset_hwid

Request Body
json
{
  "action": "validate",          // validate | info | reset_hwid
  "key": "A1B2-C3D4-E5F6-G7H8",
  "hwid": "ABC123-PC-HARDWARE-ID",  // Real PC HWID from client
  "secret": "kv_abc123...",         // Project secret (scopes to project)
  "telegram_id": "123456789",       // Optional, for audit logs
  "telegram_username": "johndoe"    // Optional, for audit logs
}
Response
json
{
  "success": true,
  "data": {
    "valid": true,
    "plan": "MONTHLY",
    "customDays": null,
    "expires_at": "2026-03-30T12:00:00.000Z",
    "nonce": "rotated-nonce",
    "note": null
  }
}

Available Actions

validate

Check key + PC HWID. Binds HWID on first use, returns nonce.

info

Get full key info (read-only). HWID optional for match check.

reset_hwid

Remove HWID binding so the key can be activated on a new machine.

Code Examples

Copy-paste ready examples for integrating KeyVault into your application.

python
import requests
import hashlib
import subprocess

API_URL = "https://your-domain.vercel.app/api/validate"

def get_hwid():
    """Get a hardware fingerprint (motherboard UUID + disk serial)."""
    try:
        uuid = subprocess.check_output(
            "wmic csproduct get uuid", shell=True
        ).decode().split("\n")[1].strip()
        disk = subprocess.check_output(
            "wmic diskdrive get serialnumber", shell=True
        ).decode().split("\n")[1].strip()
        raw = f"{uuid}:{disk}"
        return hashlib.sha256(raw.encode()).hexdigest()
    except Exception:
        return hashlib.sha256(b"fallback-hwid").hexdigest()

PROJECT_SECRET = "kv_your_project_secret"  # from dashboard

def validate_license(key: str) -> dict:
    """Validate a license key against the KeyVault API."""
    response = requests.post(API_URL, json={
        "key": key,
        "hwid": get_hwid(),
        "secret": PROJECT_SECRET,  # scopes to your project
    }, timeout=10)

    data = response.json()

    if data.get("success"):
        print(f"✅ License valid! Plan: {data['data']['plan']}")
        print(f"   Expires: {data['data']['expiresAt'] or 'Never'}")
        print(f"   Note: {data['data'].get('note', 'N/A')}")
        print(f"   Server Nonce: {data['data']['nonce']}")
        return data["data"]
    else:
        print(f"❌ Validation failed: {data.get('error')}")
        return None

# Usage
result = validate_license("XXXX-XXXX-XXXX-XXXX")
if result:
    # Continue application execution with server variable
    server_var = result.get("serverVar")
    note = result.get("note")

License Plans

KeyVault supports flexible licensing with 5 built-in plan types.

PlanDurationDescription
DAILY24 hoursShort-term trial or daily access
WEEKLY7 daysWeekly subscription period
MONTHLY30 daysStandard monthly license
LIFETIME∞ Never expiresPermanent access, one-time purchase
CUSTOM1–3650 daysSet any duration via customDays field

Error Codes

All API responses follow a consistent format. Errors include an HTTP status code and a message.

json
// Error response format
{
  "success": false,
  "error": "Human-readable error message"
}
CodeMeaningCommon Causes
400Bad RequestMissing fields, invalid plan, bad payload
401UnauthorizedInvalid or missing auth token, invalid key
403ForbiddenKey expired, HWID mismatch, max sessions, banned
404Not FoundKey doesn't exist
415Unsupported MediaWrong Content-Type header
429Rate LimitedToo many requests from IP or key
500Server ErrorInternal error, contact admin