Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.authforge.cc/llms.txt

Use this file to discover all available pages before exploring further.

Requirements

  • Node.js 18.0 or later
  • No runtime dependencies beyond Node.js built-ins

Installation

Install from npm as @authforgecc/sdk:
npm install @authforgecc/sdk
The package ships authforge.mjs and TypeScript declarations (authforge.d.ts).
Prefer a single file in-repo? Copy authforge.mjs from GitHub. The npm package is recommended for versioning and updates.

TypeScript

Use the same import as JavaScript; types resolve from the package:
import { AuthForgeClient } from "@authforgecc/sdk";

Quick start

import { AuthForgeClient } from "@authforgecc/sdk";
import * as readline from "node:readline/promises";

const client = new AuthForgeClient({
    appId: "YOUR_APP_ID",
    appSecret: "YOUR_APP_SECRET",
    publicKey: "YOUR_PUBLIC_KEY",
    heartbeatMode: "SERVER",
});

const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const key = await rl.question("Enter license key: ");
rl.close();

if (await client.login(key)) {
    console.log("Authenticated!");
    // Your app logic here - heartbeats run in the background
} else {
    console.error("Invalid license key.");
    process.exit(1);
}

Constructor parameters

const client = new AuthForgeClient({
    appId: "YOUR_APP_ID",                     // Required - from dashboard
    appSecret: "YOUR_APP_SECRET",             // Required - from dashboard
    publicKey: "YOUR_PUBLIC_KEY",             // Required - Ed25519 public key from your AuthForge dashboard (base64)
    heartbeatMode: "SERVER",                  // Required - "SERVER" or "LOCAL"
    heartbeatInterval: 900,                   // Optional - seconds (default: 900 = 15 min, any value ≥ 1 is supported)
    apiBaseUrl: "https://auth.authforge.cc",  // Optional
    onFailure: null,                          // Optional - callback(reason, exception)
    requestTimeout: 15,                       // Optional - HTTP timeout in seconds
    ttlSeconds: null,                         // Optional - requested session TTL. null = server default (24h). Clamped to [3600, 604800].
    hwidOverride: null,                       // Optional - custom identity (for example "tg:123456789")
});

ttlSeconds

Requested session token lifetime in seconds for /auth/validate. Pass null (or omit) to accept the server default of 24 hours. The server clamps to [3600, 604800] (1 hour to 7 days). The requested TTL is preserved across heartbeat refreshes so long-running apps in LOCAL mode can stretch their offline window up to 7 days.

Billing

  • Each successful login() or validateLicense() costs 1 credit (one /auth/validate debit).
  • Heartbeats cost 1 credit per 10 successful calls (billed on every 10th heartbeat). Any heartbeatInterval ≥ 1 is economically safe.
  • Revocations take effect on the next heartbeat regardless of interval.

Login

const success = await client.login(licenseKey);
Returns Promise<boolean>. It resolves to true if authentication succeeded, false otherwise. On success, the SDK starts background heartbeats automatically.

Validate license (no heartbeat)

const result = await client.validateLicense(licenseKey);
if (result.valid) {
  console.log(result.sessionToken, result.expiresIn, result.appVariables, result.licenseVariables);
} else {
  console.error(result.code, result.error);
}
Same /auth/validate request and Ed25519 verification as login, without mutating the client’s stored session or starting the heartbeat timer. Use this for bots and repeated checks; use login when you want background heartbeats. Successful results may also include sessionExpiresAt, licenseExpiresAt (null for lifetime keys), maxHwidSlots, hwidCount, and licenseLabel when present in the signed payload; the decoded payload is always available as sessionData.

Failure callback

If authentication or a heartbeat fails, the SDK calls your onFailure callback. If no callback is set (or the callback throws), the SDK exits the process.
function handleFailure(reason, exception) {
    if (reason === "login_failed") {
        console.error("Login failed - check your license key.");
        return;
    }

    if (reason === "heartbeat_failed") {
        console.error("Heartbeat failed - saving state and shutting down.");
        saveApplicationState();
    }
}

const client = new AuthForgeClient({
    appId: "YOUR_APP_ID",
    appSecret: "YOUR_APP_SECRET",
    publicKey: "YOUR_PUBLIC_KEY",
    heartbeatMode: "SERVER",
    onFailure: handleFailure,
});
If you don’t set onFailure, the SDK terminates the process immediately on any failure. Set a callback in production for graceful shutdown.

Reading variables

After successful login, app variables and license variables are available on the client:
if (await client.login(licenseKey)) {
    // App-wide variables (set in dashboard or API)
    const appVars = client.appVariables;
    if (appVars.maintenanceMode) {
        console.log("Server is under maintenance.");
        process.exit(0);
    }

    // Per-license variables
    const plan = client.licenseVariables.plan ?? "basic";
    if (plan === "pro") {
        enableProFeatures();
    }
}

Heartbeat modes

// SERVER mode - validates with the API every interval
const serverClient = new AuthForgeClient({
    appId: "YOUR_APP_ID",
    appSecret: "YOUR_APP_SECRET",
    publicKey: "YOUR_PUBLIC_KEY",
    heartbeatMode: "SERVER",
    heartbeatInterval: 900,
});

// LOCAL mode - verifies locally, re-validates when the session token expires (default 24h; up to 7d via ttlSeconds)
const localClient = new AuthForgeClient({
    appId: "YOUR_APP_ID",
    appSecret: "YOUR_APP_SECRET",
    publicKey: "YOUR_PUBLIC_KEY",
    heartbeatMode: "LOCAL",
    heartbeatInterval: 900,
});
See Heartbeat Modes for a detailed comparison.

Full example

import { AuthForgeClient } from "@authforgecc/sdk";
import * as readline from "node:readline/promises";

function saveState() {
    console.log("Saving application state...");
    // Your save logic here
}

const client = new AuthForgeClient({
    appId: "YOUR_APP_ID",
    appSecret: "YOUR_APP_SECRET",
    publicKey: "YOUR_PUBLIC_KEY",
    heartbeatMode: "SERVER",
    heartbeatInterval: 900,
    onFailure: (reason, exception) => {
        console.error(`Auth failure: ${reason}`);
        if (exception) {
            console.error(`Detail: ${exception.message ?? exception}`);
        }
        saveState();
        process.exit(1);
    },
});

const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const key = await rl.question("Enter license key: ");
rl.close();

if (!(await client.login(key))) {
    console.error("Invalid license key.");
    process.exit(1);
}

console.log("Licensed and running!");

const minVersion = client.appVariables.minVersion;
if (minVersion && APP_VERSION < minVersion) {
    console.error(`Please update to version ${minVersion} or later.`);
    process.exit(1);
}

process.on("SIGINT", () => {
    saveState();
    process.exit(0);
});

setInterval(() => {
    // Your app logic here
}, 1000);

GitHub

Full source, changelog, and issues: AuthForgeCC/authforge-node