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
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

People and identity

How Voidhash identifies the people using your app and joins their purchases, perks and events across devices.

A person is one end user of your app or website. Every purchase, perk, event and attribute in a project belongs to a person, and Studio lists them on the People page.

A person is known by one or more distinct IDs. Before sign-in the SDK uses an anonymous distinct ID it creates itself. After sign-in you call identify with your own user ID, and that becomes the person's distinct ID.

Anonymous and identified people

On first launch the SDK creates an anonymous distinct ID in the form vh_anon_<uuid> and stores it on the device. Purchases and events from that moment belong to this anonymous person, so someone can buy before creating an account.

The anonymous ID lives in app storage (UserDefaults on iOS, SharedPreferences on Android, localStorage on the web). Deleting and reinstalling an iOS app creates a new anonymous person.

Call identify with your user ID once the person signs in. Use an opaque, stable ID such as a UUID, not an email address. A distinct ID is at most 255 characters and can't start with vh_anon_.

try await voidhash.identify(externalUserId: "user_123")
voidhash.identify(externalUserId = "user_123")
await voidhash.client.identify("user_123");
await voidhash.identify("user_123");

Each SDK page covers sign-in state, failures and offline behavior: Swift, Kotlin, React Native and Web.

What identify does

SituationResult
The user ID is newThe anonymous person becomes identified under that ID.
The user ID already belongs to a personThe two people merge into one.

When two people merge, the person seen first survives. The other person's distinct IDs and push devices move to the survivor, and everything else follows:

An anonymous person who bought a subscription calls identify with a user ID that already belongs to an older person. The two merge: the older person survives, gains the anonymous distinct ID, and reads the anonymous person's purchases through the merge.Anonymous personvh_anon_… · bought pro_monthlyExisting personuser_123 · seen firstidentify("user_123")Surviving personuser_123, vh_anon_…perks from bothpurchases read through the merge

The older person survives. Purchases stay where they were made and count for the survivor.

  • Purchases, subscriptions and perks stay on the person who made them, and Voidhash reads them through the merge, so they count for the survivor. Someone who bought while anonymous keeps access after signing in to an older account. The API shows where each one came from in sourcePersonId.
  • Events keep the distinct ID they were sent with, and analytics attributes them to the survivor.
  • Attributes combine; for a key both people have, the newest value wins.

Two identified people never merge: user_123 and user_456 stay separate people. Call signOut() before a different user signs in on the same device.

Sign out

Call signOut() when the person signs out. It records a $sign_out event, starts a new anonymous person and a new session, and keeps the analytics consent setting. reset() does the same; on Web and React Native it records no $sign_out.

The same person on every platform

A distinct ID names one person per project. Call identify with the same user ID in your iOS app, Android app and website, and all three resolve to the same person. Perks belong to the person, so a subscription bought on the App Store unlocks your website and Android app too, and revenue from every store lands on one profile.

Attributes

Attributes describe a person, such as plan_interest or signup_source. Values are flat strings, numbers, booleans or null; nested objects are dropped. The keys email and name fill the person's profile fields.

  • Set: the newest value wins. Every SDK has setPersonAttributes.
  • Set once: keeps the first value and never overwrites a set value. Use it for facts like first_seen_source. Set-once is available from your backend libraries, the API and the CLI (voidhash person edit --set-once), not from the client SDKs.

People in Studio

Studio's People page lists every person in the project. A profile shows their purchases with each one's status, their perks, and any feature flag overrides, and lets admins erase their personal data. See Find people in Studio. Attributes and events aren't on the profile; list them with voidhash events list --person user_123.

Perks come only from purchases

Studio, the API, the CLI and the MCP server can't grant or revoke a perk by hand, so every entitlement comes from a subscription or a purchase. To give someone access, record a purchase, for example through a payment source, or attach the perk to a product they own.

To erase a person for a privacy request, see Delete personal data.

Why does this person have access?

To find out why someone has or lacks a perk, ask the CLI or an AI agent through the MCP server:

voidhash person why user_123 premium

The MCP tool is explain_person_access. Both walk the chain from perk to product, store product, purchase and entitlement, mark the first broken link, and suggest a fix: a product that doesn't grant the perk, an unmapped store product, an expired subscription, a purchase made while anonymous, or one in the test environment. Only production purchases count.

Next steps

  • Identify users in your SDK: Swift, Kotlin, React Native or Web.
  • Events: what a person does, recorded for analytics.
  • Check access from your backend with Node.js, PHP, Go, Rust or over HTTP.
  • Delete personal data.

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

PreviousSubscription lifecycleNextEvents

On this page

Anonymous and identified peopleWhat identify doesSign outThe same person on every platformAttributesPeople in StudioWhy does this person have access?Next steps