Node.js SDK integration
The GetPassive SDK is a Node.js package, @getpassive/sdk. It connects to the GetPassive gateway over a secure WebSocket, authenticates with your developer API key, and relays approved bandwidth sessions through the device the SDK is running on.
1. Prerequisites
- Node.js 18 or newer.
- An approved developer account at app.getpassive.io.
- At least one app created in the console. The console returns a developer API key when the app is created.
2. Configure the private registry
The package is published on the GetPassive private npm registry. Add an .npmrc file at the root of your project that points the @getpassive scope at the registry:
@getpassive:registry=https://npm.getpassive.io/
//npm.getpassive.io/:_authToken=${GETPASSIVE_NPM_TOKEN}
Request a registry token from the console. Store it in an environment variable, not in the file itself.
3. Install the package
npm install @getpassive/sdk
The package ships ES modules and a TypeScript declaration file. Its single runtime dependency is the ws WebSocket client.
4. Quickstart
import { GetPassiveClient } from '@getpassive/sdk';
const client = new GetPassiveClient({
devApiKey: process.env.GETPASSIVE_DEV_API_KEY,
onStatus(status) {
console.log('GetPassive status:', status);
},
onError(err) {
console.error('GetPassive error:', err);
},
});
await client.start();
process.on('SIGINT', async () => {
await client.stop();
process.exit(0);
});
5. Constructor options
| Option | Type | Default | Notes |
|---|---|---|---|
devApiKey | string | required | Developer API key from the console. Keep it server-side only. |
deviceUuid | string | crypto.randomUUID() | Stable identifier for this installed device. Persist it across restarts. |
gateway | string | wss://sdk.getpassive.io/ | Gateway WebSocket URL. Override only if instructed. |
publicIp | string | null | auto-detected | If omitted the SDK detects the public IP at startup. Pass null to skip detection. |
clientVersion | string | SDK version | Reported in the handshake for diagnostics. |
log | object | console | Logger with info, warn, error, and debug methods. |
onStatus | function | — | Called with each status change. |
onError | function | — | Called with errors that occur during the run loop. |
6. Status lifecycle
The status callback receives one of these values:
idle— the client has been constructed butstart()has not been called.connecting— the first connection attempt is in progress.connected— the WebSocket is open and the handshake has been sent.reconnecting— the connection dropped and the client is waiting before retrying.closed—stop()has completed.
7. Reconnect behaviour
The SDK keeps a long-lived secure WebSocket connection to the GetPassive gateway. If the connection closes or fails, it automatically reconnects with exponential backoff that starts at 1 second and doubles up to a maximum of 30 seconds (1s, 2s, 4s, 8s, 16s, 30s, 30s…). The backoff resets after a successful connection and handshake. Stopping the client cancels the loop.
8. Persisting deviceUuid
If deviceUuid is not provided the SDK generates one with crypto.randomUUID(). For production apps, persist this value across restarts so the same installation keeps a stable identity. A common pattern is to write the UUID to your application's data directory the first time the SDK starts and pass it back on every subsequent run:
import { readFile, writeFile, mkdir } from 'node:fs/promises';
import path from 'node:path';
import { randomUUID } from 'node:crypto';
import { GetPassiveClient } from '@getpassive/sdk';
async function loadDeviceUuid(dataDir) {
const file = path.join(dataDir, 'getpassive-device-uuid');
try {
return (await readFile(file, 'utf8')).trim();
} catch {
const uuid = randomUUID();
await mkdir(dataDir, { recursive: true });
await writeFile(file, uuid, 'utf8');
return uuid;
}
}
const deviceUuid = await loadDeviceUuid('/var/lib/my-app');
const client = new GetPassiveClient({
devApiKey: process.env.GETPASSIVE_DEV_API_KEY,
deviceUuid,
});
await client.start();
9. Test mode and live mode
New developer API keys start in test mode. Test mode is for integration checks, status callbacks, restart loops, and end-to-end validation while the app is under review. Live mode is enabled by an admin after review. The same SDK code path runs in both modes — you do not need to change your integration when a key is promoted.
Last updated June 11, 2026