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

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) don't require authentication.

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.

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 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

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