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
| Variable | Description |
|---|---|
CORELICENSE_KEY | License key from admin (CL-... or CL1.<base64url-api>.CL-...) |
CORELICENSE_PRODUCT_ID | Product ID on the License Server |
Optional (SDK handles automatically if not set)
| Variable | Description | Default |
|---|---|---|
CORELICENSE_API_URL | Override License API URL | From CL1.* key or api.corelicense.net |
CORELICENSE_PUBLIC_KEY | Pin public key (SPKI PEM) | Auto-fetch from server |
CORELICENSE_CACHE_PATH | Cache directory | ~/.cache/corelicense/<scope> (scope = 16-char hash of productId:licenseKey) |
APP_DOMAIN | Deploy 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.jsonafter successful boot) - Domain/instance fingerprint (
hostnameorAPP_DOMAINif set)
loadOptionsFromEnv() throws ConfigError (CONFIG_MISSING_ENV) if required variables are missing.
4. CoreLicenseOptions (constructor)
| Field | Type | Default | Description |
|---|---|---|---|
productId | string | — | Required |
licenseKey | string | — | Required |
apiUrl | string | auto | License Server base URL |
publicKey | string | — | Pin SPKI PEM |
cachePath | string | ~/.cache/corelicense/<scope> | Cache directory (override with CORELICENSE_CACHE_PATH) |
checkIntervalMs | number | 21600000 (6h) | Background refresh; 0 = disabled |
requestTimeoutMs | number | 5000 | HTTP timeout |
offlineGrace | boolean | true | Allow 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.instanceId | string | — | Required when strategy: 'fixed' |
instance.domain | string | — | App domain (for hash) |
instance.customId | string | — | When strategy: 'custom' |
audit.enabled | boolean | true | Write local audit log |
audit.path | string | {cachePath}/audit.log | Audit file path |
appVersion | string | — | Sent 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) orcheck(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.