Skip to main content

Installation

1

Install the package

Install the KeyBox SDK using your preferred package manager:
npm install keybox-sdk
2

Import the SDK

The SDK uses ES modules. Import the functions you need:
import { activateLicense, startLicenseDaemon, protectNodeApp } from 'keybox-sdk';
Make sure your package.json includes "type": "module" or use .mjs file extensions.
3

Get your license key

Obtain a license key from your KeyBox dashboard or from your end users.

Quick Start

Protect an Express App

The fastest way to add license protection to an Express application:
index.js
import express from 'express';
import { protectNodeApp } from 'keybox-sdk';

const app = express();

app.get('/', (req, res) => {
  res.json({ message: 'Hello from licensed app!' });
});

// Protect your app with a single function call
await protectNodeApp({
  app,
  port: 3000,
  productName: 'My API',
  key: process.env.LICENSE_KEY
});

console.log('App is protected and running!');
The protectNodeApp function will:
  1. Activate the license (throws error if invalid)
  2. Start your Express server
  3. Begin background validation
  4. Automatically shutdown if license is revoked or expires

API Reference

activateLicense

Activates a license key for your product. Call this once before starting your application.
import { activateLicense } from 'keybox-sdk';

const result = await activateLicense({
  productName: 'My Product',
  key: 'license-key-here',
  apiUrl: 'https://api-keybox.vercel.app', // optional
  endpoint: '/validate/activate' // optional
});

console.log(result);
// {
//   success: true,
//   valid: true,
//   status: 'active',
//   expiresAt: '2026-12-31T23:59:59Z'
// }

Parameters

productName
string
required
The name of your product as configured in KeyBox dashboard
key
string
required
The license key to activate
apiUrl
string
default:"https://api-keybox.vercel.app"
The KeyBox API base URL. Override for self-hosted instances.
endpoint
string
default:"/validate/activate"
The activation endpoint path

Returns

Promise<{
  success: boolean;
  valid: boolean;
  status: string;
  expiresAt?: string;
  message?: string;
}>

Throws

  • Error - If productName or key is missing
  • Error - If the license server returns an error or invalid response
  • Error - If activation fails for any reason (expired, revoked, invalid key, etc.)

Example: Error Handling

try {
  const result = await activateLicense({
    productName: 'My Product',
    key: process.env.LICENSE_KEY
  });
  
  console.log('License activated:', result.status);
  console.log('Expires at:', result.expiresAt);
} catch (error) {
  console.error('Failed to activate license:', error.message);
  process.exit(1);
}

startLicenseDaemon

Starts a background daemon that validates the license every 15 minutes. Automatically handles license revocation and expiration.
import { startLicenseDaemon } from 'keybox-sdk';

await startLicenseDaemon({
  productName: 'My Product',
  key: 'license-key-here',
  apiUrl: 'https://api-keybox.vercel.app', // optional
  endpoint: '/validate', // optional
  onRevoke: (data) => {
    console.error('License revoked!', data);
    process.exit(1);
  }
});

Parameters

productName
string
required
The name of your product as configured in KeyBox dashboard
key
string
required
The license key to validate
apiUrl
string
default:"https://api-keybox.vercel.app"
The KeyBox API base URL
endpoint
string
default:"/validate"
The validation endpoint path
onRevoke
function
required
Callback function invoked when license becomes invalid (revoked, expired, or invalid)
(data: {
  valid: boolean;
  status: string;
  message?: string;
}) => void

Behavior

1

Initial validation

Validates the license immediately when called
2

Background checks

Sets up a recurring validation every 900 seconds (15 minutes)
3

State monitoring

Tracks license state changes and calls onRevoke when:
  • Status is revoked
  • Status is expired
  • Status is invalid
  • valid field is false
4

Graceful errors

Network errors and server errors keep your app running - only permanent failures trigger onRevoke
The validation interval is fixed at 15 minutes to balance license enforcement with API costs.

Example: Manual Daemon Management

import { startLicenseDaemon, stopLicenseDaemon } from 'keybox-sdk';

// Start the daemon
await startLicenseDaemon({
  productName: 'My Product',
  key: process.env.LICENSE_KEY,
  onRevoke: (data) => {
    console.error(`License ${data.status}: ${data.message}`);
    cleanup();
    process.exit(1);
  }
});

// Your application code here
startServer();

// Stop the daemon on shutdown
process.on('SIGINT', () => {
  stopLicenseDaemon();
  process.exit(0);
});

stopLicenseDaemon

Stops the background license validation daemon.
import { stopLicenseDaemon } from 'keybox-sdk';

stopLicenseDaemon();
Only call this when you’re shutting down your application. Stopping the daemon disables license enforcement.

protectNodeApp

All-in-one function that activates a license, starts your Express server, and begins background validation. Automatically shuts down the server if the license is revoked.
import express from 'express';
import { protectNodeApp } from 'keybox-sdk';

const app = express();

app.get('/health', (req, res) => {
  res.json({ status: 'healthy' });
});

await protectNodeApp({
  app,
  port: 3000,
  productName: 'My API',
  key: process.env.LICENSE_KEY,
  apiUrl: 'https://api-keybox.vercel.app' // optional
});

Parameters

app
Express
required
Your Express application instance
port
number
required
The port to run your server on
productName
string
required
The name of your product as configured in KeyBox
key
string
required
The license key
apiUrl
string
default:"https://api-keybox.vercel.app"
The KeyBox API base URL

Behavior

1

Activate license

Calls activateLicense() - throws error if activation fails
2

Start server

Starts your Express app on the specified port
3

Start daemon

Begins background validation with automatic shutdown on revocation
4

Graceful shutdown

On license revocation:
  1. Stops accepting new connections
  2. Closes the server gracefully
  3. Exits the process with code 1

Example: Environment Configuration

server.js
import express from 'express';
import { protectNodeApp } from 'keybox-sdk';
import dotenv from 'dotenv';

dotenv.config();

const app = express();
app.use(express.json());

app.get('/', (req, res) => {
  res.json({ message: 'API is running' });
});

app.get('/api/users', (req, res) => {
  res.json({ users: [] });
});

// Protect the entire application
await protectNodeApp({
  app,
  port: parseInt(process.env.PORT || '3000'),
  productName: process.env.PRODUCT_NAME,
  key: process.env.LICENSE_KEY,
  apiUrl: process.env.KEYBOX_API_URL
});
.env
PORT=3000
PRODUCT_NAME=My API
LICENSE_KEY=kb_xxxxxxxxxxxxx
KEYBOX_API_URL=https://api-keybox.vercel.app

Complete Examples

Example 1: Basic Express API

index.js
import express from 'express';
import { protectNodeApp } from 'keybox-sdk';

const app = express();
app.use(express.json());

app.get('/api/data', (req, res) => {
  res.json({
    data: 'This endpoint is protected by KeyBox',
    timestamp: new Date().toISOString()
  });
});

app.post('/api/data', (req, res) => {
  res.json({
    received: req.body,
    message: 'Data saved successfully'
  });
});

try {
  await protectNodeApp({
    app,
    port: 3000,
    productName: 'My API',
    key: process.env.LICENSE_KEY
  });
  console.log('✓ Licensed API running on http://localhost:3000');
} catch (error) {
  console.error('✗ Failed to start:', error.message);
  process.exit(1);
}

Example 2: CLI Tool with Manual Control

cli.js
import { activateLicense, startLicenseDaemon } from 'keybox-sdk';

// Activate on startup
try {
  await activateLicense({
    productName: 'My CLI Tool',
    key: process.env.LICENSE_KEY
  });
  console.log('✓ License activated');
} catch (error) {
  console.error('✗ License activation failed:', error.message);
  console.error('Please contact support with a valid license key.');
  process.exit(1);
}

// Start background validation
await startLicenseDaemon({
  productName: 'My CLI Tool',
  key: process.env.LICENSE_KEY,
  onRevoke: (data) => {
    console.error('\n⚠ License has been revoked or expired');
    console.error(`Status: ${data.status}`);
    console.error('The tool will now exit.');
    process.exit(1);
  }
});

console.log('✓ License monitoring active');
console.log('Running your CLI tool...\n');

// Your CLI tool logic here
runCliTool();

Example 3: Next.js API Route

pages/api/protected.js
import { activateLicense } from 'keybox-sdk';

let licenseValid = false;

// Validate license once when the API route is first loaded
if (!licenseValid) {
  try {
    await activateLicense({
      productName: 'My Next.js App',
      key: process.env.LICENSE_KEY
    });
    licenseValid = true;
  } catch (error) {
    console.error('License validation failed:', error.message);
  }
}

export default function handler(req, res) {
  if (!licenseValid) {
    return res.status(403).json({
      error: 'Invalid license',
      message: 'This application is not properly licensed'
    });
  }
  
  res.status(200).json({
    message: 'This API route is protected by KeyBox',
    data: { timestamp: new Date().toISOString() }
  });
}

Example 4: Custom Revocation Handler

app.js
import express from 'express';
import { activateLicense, startLicenseDaemon } from 'keybox-sdk';

const app = express();

app.get('/', (req, res) => {
  res.json({ status: 'running' });
});

// Activate license
const activationResult = await activateLicense({
  productName: 'My App',
  key: process.env.LICENSE_KEY
});

console.log('License activated:', {
  status: activationResult.status,
  expiresAt: activationResult.expiresAt
});

// Start server
const server = app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

// Start daemon with custom revocation logic
await startLicenseDaemon({
  productName: 'My App',
  key: process.env.LICENSE_KEY,
  onRevoke: async (data) => {
    console.error('\n===========================================');
    console.error('LICENSE REVOCATION DETECTED');
    console.error('===========================================');
    console.error(`Status: ${data.status}`);
    console.error(`Message: ${data.message || 'License no longer valid'}`);
    console.error('===========================================\n');
    
    // Send alerts to monitoring service
    await sendAlert({
      type: 'license_revoked',
      data
    });
    
    // Log to database
    await logLicenseEvent('revoked', data);
    
    // Graceful shutdown
    console.log('Shutting down server...');
    server.close(() => {
      console.log('Server closed');
      process.exit(1);
    });
    
    // Force exit after 5 seconds
    setTimeout(() => {
      console.error('Force exiting...');
      process.exit(1);
    }, 5000);
  }
});

console.log('License daemon started');

Logging

The SDK logs all license-related events to the console:
[2026-03-05T10:30:00.000Z] [KEYBOX] [INFO] Activating license {"productName":"My API"}
[2026-03-05T10:30:01.000Z] [KEYBOX] [INFO] License activated
[2026-03-05T10:30:01.100Z] [KEYBOX] [INFO] Licensed app running at http://localhost:3000
[2026-03-05T10:30:01.200Z] [KEYBOX] [INFO] License daemon started {"intervalSeconds":900}
Log levels:
  • INFO - Normal operations
  • WARN - Temporary errors (network issues, server errors)
  • ERROR - Permanent failures (revoked, expired, invalid)

Troubleshooting

Error: “productName and key are required”

Make sure you’re passing both parameters:
await activateLicense({
  productName: 'My Product', // Required
  key: 'kb_xxxxxxxxxxxxx'    // Required
});

Error: “License server did not return JSON”

This usually means:
  1. The API URL is incorrect
  2. There’s a network issue
  3. A proxy is intercepting the request
Check your apiUrl parameter and network connectivity.

License validation keeps failing

Check:
  1. License key is correct
  2. Product name matches exactly (case-sensitive)
  3. License is not expired or revoked in the dashboard
  4. Server can reach https://api-keybox.vercel.app

App doesn’t shutdown on revocation

Make sure:
  1. You’ve provided an onRevoke callback
  2. The callback calls process.exit(1)
  3. No code is preventing process exit

TypeScript Support

While the SDK is written in JavaScript, you can use it with TypeScript:
index.ts
import { activateLicense, startLicenseDaemon, protectNodeApp } from 'keybox-sdk';
import express, { Express } from 'express';

const app: Express = express();

app.get('/', (req, res) => {
  res.json({ message: 'Hello TypeScript!' });
});

interface LicenseConfig {
  app: Express;
  port: number;
  productName: string;
  key: string;
}

const config: LicenseConfig = {
  app,
  port: 3000,
  productName: 'My API',
  key: process.env.LICENSE_KEY || ''
};

await protectNodeApp(config);

Next Steps

Python SDK

Explore the Python SDK for FastAPI apps

.NET SDK

Learn about the .NET SDK for ASP.NET Core

API Reference

Complete API endpoint documentation

Examples

More integration examples and patterns

Build docs developers (and LLMs) love