VoidhashDocs
DevelopersHelp centerGuidesAPI reference
Dashboard
Get started
Introduction
Quickstart
How Voidhash works
Glossary
Versions and releases
Concepts
Teams, projects and environments
API keys
Products and perks
Offers
Subscription lifecycle
People and identity
Groups
Events
Features
Paywalls in your app
Feature flags and A/B tests
Paywall components
Push notifications
Ad attribution in your app
Client SDKs
React Native
Swift
Kotlin
Web
Your backend
Node.js
PHP
Go
Rust
Other languages
Payment sources
Forward store notifications
Developer tools
CLI
MCP server
Query analytics with VoidQL
Node.js library
Check access
Receive webhooks
Persons and events
Custom payment providers

Persons and events

Create and update persons, capture events, describe groups, send push notifications and erase data from Node.js.

Node.js code for persons, events and push notifications, using a configured client.

Persons

Create a person

const person = await voidhash.persons.create({
  payload: { distinctId: "user_123", email: "ada@example.com", name: "Ada" },
});

console.log(person.id); // person_…

email and name can be null.

Find a person

list filters by distinct ID or email:

const { data } = await voidhash.persons.list({ params: { distinctId: "user_123" } });
const person = data[0]; // undefined when Voidhash has never seen user_123

const byEmail = await voidhash.persons.list({ params: { email: "ada@example.com" } });

get rejects with person_not_found for an unknown or erased ID.

const person = await voidhash.persons.get({ params: { personId: "person_k2v9x4m8q1r3" } });

listSubscriptions, listPurchases and listEntitlements take the same personId.

Update attributes

update sets attributes:

await voidhash.persons.update({
  params: { personId: "person_k2v9x4m8q1r3" },
  payload: {
    traits: { plan: "team", seats: 5 },
    setOnce: { signupSource: "website" },
  },
});

Capture events

eventCapture.capture takes timestamp as an ISO 8601 string.

Create the client with ingestUrl: "https://api.voidhash.com"; the default capture host doesn't answer yet.

await voidhash.eventCapture.capture({
  distinctId: "user_123",
  event: "report_exported",
  timestamp: new Date().toISOString(),
  properties: { format: "csv", rows: 1200 },
});

eventCapture.batch sends an array in one request; an empty array sends nothing.

const { accepted, rejected } = await voidhash.eventCapture.batch([
  { distinctId: "user_123", event: "trial_reminder_sent", timestamp: new Date().toISOString() },
  { distinctId: "user_456", event: "trial_reminder_sent", timestamp: new Date().toISOString() },
]);

Errors carry an event capture code.

Groups

Groups are what your users belong to, such as their company. Name an event's groups with groups, by group type; they are sent as its $groups property:

await voidhash.eventCapture.capture({
  distinctId: "user_123",
  event: "report_exported",
  timestamp: new Date().toISOString(),
  groups: { company: "acme" },
});

eventCapture.groupIdentify sets a group's properties, such as what your backend knows of a company's plan and seats. setOnce fills only properties the group has no value for, and a later change of a property wins. timestamp defaults to now.

await voidhash.eventCapture.groupIdentify({
  groupType: "company",
  groupKey: "acme",
  properties: { name: "Acme", plan: "pro", seats: 40 },
  setOnce: { firstPlan: "trial" },
});

The $groupidentify event it sends belongs to no person.

Send push notifications

Early access

Push notifications are in early access. Ask us on Discord, or email support@voidhash.com on a paid plan, to turn them on for your team.

Pass an idempotency-key so a retry returns the first send instead of notifying twice.

const sent = await voidhash.pushNotifications.create({
  params: { "idempotency-key": "renewal-reminder-user_123-2026-11" },
  payload: {
    distinctIds: ["user_123"],
    title: "Your trial ends tomorrow",
    body: "Keep Pro for $9.99 a month.",
    data: { screen: "paywall" },
  },
});

console.log(sent.id, sent.deviceCount, sent.unresolvedDistinctIds);

pushNotifications.listDeliveries({ params: { pushNotificationId: sent.id } }) follows delivery; see Send a push.

Erase personal data

persons.createErasure takes exactly one of distinctId or personId and needs project:persons:delete.

const erasure = await voidhash.persons.createErasure({ payload: { distinctId: "user_123" } });

const status = await voidhash.persons.getErasure({ params: { erasureId: erasure.id } });
console.log(status.status); // queued | in_progress | completed | failed

Delete personal data explains what is kept.

Erasure can't be undone

The person's identity and attributes are gone for good. Purchases and revenue stay recorded against an anonymized person.

Next steps

  • Receive webhooks
  • People and identity
  • Events

Something wrong or missing on this page? Tell us by email or on Discord.

PreviousReceive webhooksNextCustom payment providers

On this page

PersonsCreate a personFind a personUpdate attributesCapture eventsGroupsSend push notificationsErase personal dataNext steps