Skip to content

Node.js SDK

The Node.js 18+ SDK is @dycrypt/license. It includes ESM, CommonJS, and TypeScript declarations with no runtime dependencies.

Until the package is published to the public npm registry, install it from the DYCRYPT SDK checkout:

Terminal window
npm install /path/to/dycrypt/sdk/node

A single-file ESM version is also available as sdk/node/src/dycrypt-license.mjs.

import { fingerprint } from '@dycrypt/license';
if (process.argv.includes('--fingerprint')) {
console.log(fingerprint());
process.exit(0);
}

Use this before issuing an Offline or offline-activated Hybrid licence.

import { LicenseVerifier, Policy } from '@dycrypt/license';
import { readFileSync } from 'node:fs';
const verifier = new LicenseVerifier({
publicKey: readFileSync('product-public-key.pem', 'utf8'),
productKey: 'your-product-key',
issuerUrl: 'https://app.dycrypt.com',
orgSlug: 'your-org-slug',
checkId: '<the product’s check id>',
checkToken: 'dycc_...',
policy: Policy.ADVISORY,
timeoutMs: 5_000,
});

Omit issuerUrl, orgSlug, checkId, checkToken, and policy for Offline. Build the verifier once and reuse it.

checkId and checkToken are required alongside issuerUrl; the constructor throws if one is missing, rather than failing later on every check. Copy all four values from the product’s Quick Start Guide. The token ships inside your application, so treat it as identifying rather than secret.

Every answer from DYCRYPT is signed with the product’s key, and the verifier checks that signature before recording a successful check. requireReceipt defaults to true; leaving it on is what makes the check mean something.

const result = verifier.verify(readFileSync('customer.lic', 'utf8'));
enforce(result);

verify() is synchronous, never touches the network, and returns INVALID for malformed input, a wrong product, an unsupported schema, or a machine mismatch.

const result = await verifier.check(
readFileSync('customer.lic', 'utf8'),
);
enforce(result);

Call check() at startup and schedule later calls at the product’s signed interval. The SDK starts no timer. Keep the verifier for the process lifetime so it retains successful-check state and cached results.

A renewed licence answers check() with valid: false and online.status === 'ACTIVE' — the old string no longer verifies, but the issuer confirms a current one exists. If the product has turned on self-service fetch, ask for it directly instead of prompting the customer to install a new file by hand:

const current = await verifier.fetchLatest(licenseText);
if (current) {
await writeFile('customer.lic', current, 'utf8');
}

fetchLatest() presents the licence you already hold as the credential — the current one, or an earlier, superseded term for the same licence id — and resolves to null if the issuer refuses, is unreachable, or answers with something that does not itself verify. It runs the result back through verify() before returning it, so a caller never has to trust the transport. Call it only when you decide to, never automatically from inside check(). It is opt-in per product and refused once the licence you present is past its own expiry and grace; see the licence check API for the full protocol.

import { Status } from '@dycrypt/license';
function enforce(result) {
switch (result.status) {
case Status.ACTIVE:
return;
case Status.GRACE:
console.warn('Licence is inside its expiry grace period');
return;
case Status.STALE:
throw new Error('Reconnect to refresh the licence status');
case Status.PENDING:
throw new Error(`Licence starts at ${result.startsAt}`);
case Status.REVOKED:
case Status.EXPIRED:
case Status.INVALID:
case Status.UNKNOWN:
throw new Error(`Unlicensed (${result.status}): ${result.reason}`);
}
}

ACTIVE and GRACE are the only statuses with valid === true.

const maxUsers = result.getInt('maxUsers', 5);
const edition = result.getString('edition', 'standard');
const exportEnabled = result.getBool('exportEnabled', false);
const features = result.getStringList('features', []);

Use result.checkedOnline to distinguish a real issuer answer from a local fallback and result.onlineError to log why an online request did not complete.