Node.js library
A typed server-side client for the Voidhash API, with Promise and Effect entrypoints.
@voidhash/node wraps the REST API in typed methods for Node.js backends, with
Promise and Effect entrypoints. It needs a secret key, so run it
on your server only.
Install
@voidhash/node installs from the Voidhash package registry, pkg.voidha.sh. branch:main names the
newest build:
npm install @voidhash/node@https://pkg.voidha.sh/@voidhash/node/branch:mainTo pin a build, install from https://pkg.voidha.sh/@voidhash/node/<hash>, using the short commit hash at
the end of the installed version, such as 83f7412 in 0.0.1-alpha.1-g83f7412.
The library is an alpha release and isn't on npm yet: npm install @voidhash/node installs an
older preview that doesn't match these docs. Builds are kept for three weeks, so pin a recent one
and update regularly. See Versions and releases.
Requirements: Node.js 18 or later with a global fetch. Loading the library with require()
also needs Node.js 20.19+ or 22.12+, because it depends on the ESM-only effect package. import
has no such limit.
Create a client
Create one client with your secret key and share it across your server:
import { createVoidhashSdk } from "@voidhash/node";
export const voidhash = createVoidhashSdk({
secretKey: process.env.VOIDHASH_SECRET_KEY!,
// Event capture is served from the API host for now.
ingestUrl: "https://api.voidhash.com",
});| Option | Default | Description |
|---|---|---|
secretKey | — | Required. Sent as Authorization: Bearer <secretKey>. |
projectId | The key's project | Skips the project lookup. Concurrent first calls share one lookup. |
baseUrl | https://api.voidhash.com | The API origin, http: or https:. |
ingestUrl | https://ingest.voidhash.com | The event capture origin. Use https://api.voidhash.com; the default host doesn't answer yet. |
publishableKey | — | Sent as the body token on event capture. Optional. |
headers | {} | Extra headers for every request. |
createVoidhashSdk makes no request, but throws VoidhashNodeConfigurationError at once when
secretKey or projectId is blank, a URL is invalid, there is no global fetch, or headers sets
Authorization or x-secret-key.
Call the API
Namespaces follow the API reference groups, such as persons, products, perks and
webhooks, and methods are named after its operations. Each method takes one object: params
for path, query and header parameters, payload for the JSON body.
const product = await voidhash.products.get({ params: { productId: "prod_m4q8x2v9k1r7" } });
await voidhash.products.update({
params: { productId: "prod_m4q8x2v9k1r7" },
payload: { name: "Pro monthly" },
});List methods return one page as { data, pageInfo }:
let cursor: string | undefined;
do {
const page = await voidhash.perks.list({ params: { limit: 50, cursor } });
for (const perk of page.data) console.log(perk.slug);
cursor = page.pageInfo.hasNextPage ? (page.pageInfo.endCursor ?? undefined) : undefined;
} while (cursor);The client also has entitlements for access checks,
eventCapture for events, and
paymentSource() for payment sources.
Handle errors
A failed call rejects. getVoidhashApiError(error) returns the API error
as { type, code, message, param, status, requestId }, or undefined for any other failure.
import { getVoidhashApiError } from "@voidhash/node";
try {
return await voidhash.products.get({ params: { productId: "prod_m4q8x2v9k1r7" } });
} catch (error) {
switch (getVoidhashApiError(error)?.type) {
case "not_found":
return null;
case "unauthenticated":
case "permission_denied":
throw new Error("The Voidhash secret key is invalid or lacks access.");
default:
throw error;
}
}Network failures (DNS, TLS, timeouts) and undocumented statuses reject with an Effect
HttpClientError. The library doesn't retry or cache.
Effect entrypoint
@voidhash/node/effect exposes the same client with every method returning an Effect instead of
a Promise:
import { createVoidhashSdk } from "@voidhash/node/effect";
const voidhash = createVoidhashSdk({ secretKey: process.env.VOIDHASH_SECRET_KEY! });
const program = voidhash.entitlements.hasActivePerk({
distinctId: "user_123",
perkSlug: "premium",
});It shares Effect types with your app, so your app must resolve the same effect version as the
library; Effect v4 is in beta, and its types change between releases. Webhook helpers are the same
in both entrypoints.
Next steps
Something wrong or missing on this page? Tell us by email or on Discord.