Installation

Install the package, configure environment variables, and run boot() for the first time.

1. Install package

npm install @corelicense/node

Peer dependencies (framework-specific)

Install only when using the corresponding integration:

npm install express              # Express middleware
npm install fastify              # Fastify plugin
npm install @nestjs/common @nestjs/core   # NestJS

The SDK does not require peer dependencies — tree-shaking is safe if you only use CoreLicense directly.


2. Environment variables

Required

VariableDescription
CORELICENSE_KEYLicense key from admin (CL-... or CL1.<base64url-api>.CL-...)
CORELICENSE_PRODUCT_IDProduct ID on the License Server

Optional (SDK handles automatically if not set)

VariableDescriptionDefault
CORELICENSE_API_URLOverride License API URLFrom CL1.* key or api.corelicense.net
CORELICENSE_PUBLIC_KEYPin public key (SPKI PEM)Auto-fetch from server
CORELICENSE_CACHE_PATHCache directory~/.cache/corelicense/<scope> (scope = 16-char hash of productId:licenseKey)
APP_DOMAINDeploy domain (instance ID)hostname() or URL from PaaS env (see below)

Auto-detected domain variables (in order): APP_DOMAIN, CORELICENSE_APP_DOMAIN, APP_URL, PUBLIC_APP_URL, VERCEL_URL, RAILWAY_PUBLIC_DOMAIN, RENDER_EXTERNAL_URL.

API URL resolution order (no manual config needed in production):

  • options.apiUrl / CORELICENSE_API_URL
  • URL embedded in CL1.<base64url>.CL-... key
  • Cache sdk.endpoint.json
  • https://api.corelicense.net

Local development

CORELICENSE_KEY=CL-AAAAA-BBBBB-CCCCC-DDDDD-EEEEE
CORELICENSE_PRODUCT_ID=demo
CORELICENSE_API_URL=http://localhost:8080

Production

CORELICENSE_KEY=CL1.xxxxx.CL-AAAAA-BBBBB-...
CORELICENSE_PRODUCT_ID=my-product
# No CORELICENSE_API_URL needed — SDK uses api.corelicense.net

Production Go server needs SDK_PUBLIC_URL=https://api.corelicense.net when generating CL1.* keys.


3. Minimal initialization

import { CoreLicense, loadOptionsFromEnv } from '@corelicense/node';

const license = new CoreLicense(loadOptionsFromEnv());
await license.boot();

Only CORELICENSE_KEY + CORELICENSE_PRODUCT_ID in .env are required. The SDK automatically resolves:

  • API URL (from license key)
  • Public keys (fetch + cache)
  • Cache path (~/.cache/corelicense/...)
  • Instance ID (persists install.id + instance.json after successful boot)
  • Domain/instance fingerprint (hostname or APP_DOMAIN if set)

loadOptionsFromEnv() throws ConfigError (CONFIG_MISSING_ENV) if required variables are missing.


4. CoreLicenseOptions (constructor)

FieldTypeDefaultDescription
productIdstringRequired
licenseKeystringRequired
apiUrlstringautoLicense Server base URL
publicKeystringPin SPKI PEM
cachePathstring~/.cache/corelicense/<scope>Cache directory (override with CORELICENSE_CACHE_PATH)
checkIntervalMsnumber21600000 (6h)Background refresh; 0 = disabled
requestTimeoutMsnumber5000HTTP timeout
offlineGracebooleantrueAllow cached policy when server unreachable
defaultBlockMode'block' | 'limited''limited'Default middleware mode
instance.strategy'install-id-domain-hash' | 'custom' | 'fixed''install-id-domain-hash'Instance ID calculation
instance.instanceIdstringRequired when strategy: 'fixed'
instance.domainstringApp domain (for hash)
instance.customIdstringWhen strategy: 'custom'
audit.enabledbooleantrueWrite local audit log
audit.pathstring{cachePath}/audit.logAudit file path
appVersionstringSent with SDK info to server

5. boot() flow

  • Resolve API URL (pin / cache / env / default)
  • Compute instance ID (install-id-domain-hash: sha256 of productId + licenseKey + installId + domain)
  • Fetch or use pinned public key
  • Load policy token from cache → verify
  • If needed: activate (first run) or check (refresh)
  • Start background checker (if checkIntervalMs > 0)
  • requireActive() — fail-closed if license is not active

Note v0.5: When offline + grace period expired → boot() throws, app does not run silently.


6. Pin public key (enterprise)

const license = new CoreLicense(
  loadOptionsFromEnv({
    publicKey: process.env.CORELICENSE_PUBLIC_KEY,
  }),
);

When pinned, the SDK does not call GET /v1/public/products/{id}/keys. After key rotation on the server, update CORELICENSE_PUBLIC_KEY and restart the app.


7. Files on disk

~/.cache/corelicense/<scope>/   # or CORELICENSE_CACHE_PATH / cachePath
  install.id          # Install UUID (install-id-domain-hash strategy)
  instance.json       # instanceId persisted after successful boot
  policy.token        # JWT policy (signed)
  usage.json          # daily quota usage
  sdk.endpoint.json   # trusted apiUrl from server
  public.keys.json    # fetched public keys (when not pinned)
  audit.log           # audit events (JSON lines)

In production, set cachePath or CORELICENSE_CACHE_PATH to a persistent volume. Add the cache directory to your app's .gitignore.


8. Verify installation

const status = await license.getStatus();
console.log(status); // { status: 'active', ... }

const policy = await license.getPolicy();
console.log(policy?.features);

HTTP health routes (without license guard):

app.get('/health', (_req, res) => res.json({ ok: true }));
app.get('/license/status', async (_req, res) => {
  res.json(await license.getStatus());
});

9. Next steps

Integration guide — Express, NestJS, module registry, DI, worker, production checklist.

API Reference — method list and error codes.