Node.js SDK
The Node client is published as @redpennon/node-sdk. It targets Node 20+ (ESM) and points at the production API at https://api.redpennon.dev — the host is fixed; you only supply the environment API key.
Install
npm install @redpennon/node-sdk
Configure
import { RedPennonClient } from "@redpennon/node-sdk";
const client = new RedPennonClient({
apiKey: process.env.RP_API_KEY!,
});
You can inject a custom fetchImpl for tests:
new RedPennonClient({
apiKey: "test",
fetchImpl: async (url, init) => {
/* return new Response(...) */
},
});
Evaluate a variable
variableValue — value or default
const enabled = await client.variableValue("show-banner", false, {
user: { id: "user-123", email: "alice@example.com" },
});
Returns the served value cast to T, or defaultValue when value is null, the variable is unknown, or a transport/governance error occurs. Use this for the common "give me the flag value or fall back" pattern.
variable — full result
const result = await client.variable("checkout-flow", {
user: { id: "user-123" },
});
// result.value, result.variation, result.reason, result.feature,
// result.evaluation_trace (string | null)
Returns a VariableResult with all response fields. Use when you need variation, reason, or evaluation_trace.
variables — batch
const results = await client.variables(
["show-banner", "discount-pct"],
{ user: { id: "user-123" } },
);
const banner = results["show-banner"].value ?? false;
const discount = results["discount-pct"].value ?? 0;
Resolves multiple variables in one round-trip. Returns Record<string, VariableResult>.
VariableResult type
interface VariableResult {
key: string;
value: unknown; // null when not served
variation: string | null;
reason: string;
feature: string | null;
evaluation_trace?: string | null; // opaque signed token — forward to trackEvents
}
Track events
import { EventPayload } from "@redpennon/node-sdk";
// Evaluate first to capture the trace
const result = await client.variable("checkout-flow", { user: { id: "user-123" } });
// Then send the event, forwarding the trace for verified attribution
await client.trackEvents([
{
event: "purchase",
variable: "checkout-flow",
variation: result.variation!,
user: { id: "user-123" },
value: 49.99,
evaluation_trace: result.evaluation_trace ?? undefined,
},
]);
trackEvents POSTs to POST /v1/events and returns { accepted: number }. Throws APIError on non-202.
EventPayload type
interface EventPayload {
event: string; // required
variable: string; // required
variation: string; // required
user?: UserContext;
value?: number;
occurred_at?: string; // ISO-8601
evaluation_trace?: string; // from VariableResult.evaluation_trace
}
See Ingest events for full field semantics and error codes.
Errors
Non-2xx responses throw APIError with statusCode, message, and raw body. See API errors.