Resources/Developer & SDK/Node.js SDK reference

Node.js SDK reference

Every option, method and return value in @spectry/spectry.

A complete reference for @spectry/spectry. For a walkthrough, start with the Node.js SDK guide.

Client options

new SpectryClient({
  siteId: "...",              // required
  secretKey: "...",           // required — sk_live_… / sk_test_…
  apiHost: "https://api.spectry.io",
  refreshInterval: 60000,     // ms between config polls; 0 disables polling
  timeout: 3000,              // ms per network call
  eventFlushInterval: 5000,   // ms a queued event may wait before sending
  eventBatchSize: 25,         // events per request
  maxQueuedEvents: 1000,      // queue ceiling; oldest are dropped past it
  logger: console,            // or false to silence the SDK
  fetch: customFetch,         // for a proxy or a custom HTTP agent
  onError: (err, { operation }) => reportToSentry(err),
});

The event queue is bounded deliberately. An unbounded one would turn an outage on our side into your process running out of memory; past the ceiling the oldest events are dropped and the loss is logged.

SpectryClient

  • init(options?) — load the configuration and start refreshing. Resolves true/false; takes { timeout, throwOnFailure }. Calling it twice does not fetch twice.
  • createScopedInstance(context?) — a ScopedSpectry for one user. Synchronous, no network call.
  • refresh() — refresh the configuration now. Resolves true/false, never throws.
  • flush() — send queued events immediately.
  • close() — stop polling and flush. Safe to call twice.
  • ready — whether a configuration has loaded.
  • getConfig() — the cached configuration, or null. Treat as read-only.
  • getStatus() — cache and queue state, for health checks.

User context

client.createScopedInstance({
  attributes: { id: "user_123", country: "DE", plan: "scale" },
  visitorId: "anon_abc",   // optional — overrides attributes.id for bucketing
  sessionId: "sess_xyz",   // optional — ties events to a browser session
});

visitorId is useful when you want to bucket on a stable anonymous ID while still reporting a logged-in id. Pass the browser's session ID as sessionId to join server events to the same session the JavaScript SDK is recording.

ScopedSpectry

  • isOn(key) / isOff(key) — boolean check. An unknown flag is off.
  • getFeatureValue(key, fallback) — the value, or the fallback.
  • getFeature(key) — { value, on, off, source, variantKey? }.
  • getAllFeatures() — every flag resolved for this user, keyed by flag key.
  • getVariation(id) — the assignment, or null if not in the experiment.
  • getExperiments() — every experiment this user is currently in.
  • logEvent(name, properties?) — queue an event. Never throws.
  • flush() — send queued events now.
  • ready — whether the configuration has loaded.

Feature sources

What getFeature().source means, and what to do about it:

SourceMeaning
enabledA boolean flag is on for this user.
variantA multivariate flag picked a variant; variantKey names it.
disabledThe flag is switched off in the dashboard.
targetingThe user did not match the flag's targeting rules — often a missing attribute.
rolloutThe user fell outside the rollout percentage, or has no id to bucket on.
unknownFlagNo such flag. Check the key, and that it exists on this site.
notReadyThe configuration has not loaded. Check the key and getStatus().

Errors

The SDK does not throw from request-path methods. Failures are logged, passed to onError if you supply it, and otherwise absorbed. init() throws only when you pass throwOnFailure: true; the constructor throws immediately if siteId or secretKey is missing.

A SpectryHttpError carries status and isPermanent. A permanent failure (401, 403) means the credential is wrong — check the key, that it belongs to this site, that it has not been revoked, and that it carries the scope the call needs.

Testing

Pass a fake fetch to skip the network entirely and pin the configuration your tests run against:

const client = new SpectryClient({
  siteId: "test", secretKey: "sk_test_x",
  refreshInterval: 0, logger: false,
  fetch: async () => ({
    ok: true, status: 200,
    headers: { get: () => 'W/"1"' },
    text: async () => JSON.stringify({
      siteId: "test", version: 'W/"1"', generatedAt: "", experiments: [],
      flags: [{
        key: "my-feature", type: "boolean", enabled: true,
        default_value: false, variants: [], rollout_percentage: 100,
        targeting_rules: {},
      }],
    }),
  }),
});

await client.init();
client.createScopedInstance({ attributes: { id: "u1" } }).isOn("my-feature"); // true

refreshInterval: 0 disables polling so tests do not leave a timer running.


Put this to work on your own site.

Heatmaps, session replays, funnels and experiments in one platform. Set it up in minutes, no credit card needed, and 5,000 sessions a month are free forever.