Installation
Install the package
Install the KeyBox SDK using your preferred package manager:
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.
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:
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:
Activate the license (throws error if invalid)
Start your Express server
Begin background validation
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
The name of your product as configured in KeyBox dashboard
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
The name of your product as configured in KeyBox dashboard
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
Callback function invoked when license becomes invalid (revoked, expired, or invalid) ( data : {
valid : boolean ;
status : string ;
message ?: string ;
}) => void
Behavior
Initial validation
Validates the license immediately when called
Background checks
Sets up a recurring validation every 900 seconds (15 minutes)
State monitoring
Tracks license state changes and calls onRevoke when:
Status is revoked
Status is expired
Status is invalid
valid field is false
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
Your Express application instance
The port to run your server on
The name of your product as configured in KeyBox
apiUrl
string
default: "https://api-keybox.vercel.app"
The KeyBox API base URL
Behavior
Activate license
Calls activateLicense() - throws error if activation fails
Start server
Starts your Express app on the specified port
Start daemon
Begins background validation with automatic shutdown on revocation
Graceful shutdown
On license revocation:
Stops accepting new connections
Closes the server gracefully
Exits the process with code 1
Example: Environment Configuration
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
});
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
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 );
}
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
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
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:
The API URL is incorrect
There’s a network issue
A proxy is intercepting the request
Check your apiUrl parameter and network connectivity.
License validation keeps failing
Check:
License key is correct
Product name matches exactly (case-sensitive)
License is not expired or revoked in the dashboard
Server can reach https://api-keybox.vercel.app
App doesn’t shutdown on revocation
Make sure:
You’ve provided an onRevoke callback
The callback calls process.exit(1)
No code is preventing process exit
TypeScript Support
While the SDK is written in JavaScript, you can use it with TypeScript:
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