VoidhashDocs
DevelopersHelp centerGuidesAPI reference
Dashboard
Essentials
API overview
Authentication
Event capture
Push device API
Webhooks
Webhook delivery
Webhook events
Projects & keys
Projects
API keys
Audit log
Customers & access
Persons
Products
Perks
Sandbox
Paywalls
Paywalls
Paywall locations
Components
Component registry
Assets
Experiments & flags
Experiments
Feature flags
Analytics & events
Analytics
Analytics alerts
Cohorts
Group types
Groups
Events
Ingest policy
VoidQL
Tracking domains
Ads
Ads
Ad accounts
Meta measurement
Payments & stores
Payment providers
Payment provider products
Purchase history imports
Payment sources
Webhooks & notifications
Webhooks
Push notifications
Push configurations
Automations
Organization & team
Organizations
Members
Invitations
Billing
Your account
Profile
Session
Notices
Connected apps
Terms of Service
Developer tools
Schema
SDK
Retrieve the person
Identify a person
Update the person's attributes
Sync a store transaction
Sign a promotional offer
Record a development purchase
Evaluate feature flags
Resolve a paywall
Retrieve the SDK schema
Register a push device
Refresh a push device
Unregister a push device

Identify a person

Identifies the anonymous person x-distinct-id names as distinctId, your id for the user, merging the two, and returns the identified person.

From an identified distinct id it merges nothing and returns the person distinctId names, or fails with Api/SdkPersonNotFoundError when there is none. Fails with Api/SdkPersonAlreadyIdentifiedError when distinctId belongs to another identified person.

Guide: Install an SDK

Errors

This operation adds no error codes of its own. It can fail with the errors every operation shares, such as unauthenticated; see Errors.

More in SDK

  • Retrieve the person GET
  • Update the person's attributes POST
  • Sync a store transaction POST
  • Sign a promotional offer POST
  • Record a development purchase POST
  • Evaluate feature flags POST
  • Resolve a paywall POST
  • Retrieve the SDK schema GET
  • Register a push device POST
  • Refresh a push device POST
  • Unregister a push device POST

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

PreviousRetrieve the personNextUpdate the person's attributes

On this page

AuthorizationHeader parametersRequest bodyExamplesResponse bodyErrorsMore in SDK
POST
/api/v1/sdk/identify

Authorization

x-publishable-key<token>

A project publishable key, which ships inside apps. Send the end user's distinct id in x-distinct-id with it.

In: header

Header parameters

x-distinct-id*string

The distinct id of the end user the request acts for: the anonymous vh_anon_… id the SDK generated, or the id the app identified them with. At most 255 characters.

x-distinct-id-encoding?"percent"

percent when x-distinct-id holds the RFC 3986 percent-encoded UTF-8 form of an id that is not printable ASCII; leave it out when the header holds the id as is.

Value in

  • "percent"
x-publishable-key*string

The project's publishable key, vh_pk_…. A test key, vh_pk_test_…, works with store sandbox and test purchases.

x-client-bundle-id*string

The app's bundle id on iOS or package name on Android, which picks the project's store configuration for purchases and promotional offers.

x-client-locale?string

The end user's most preferred locale, such as en-US.

x-client-version?string

The app's version, such as 2.4.1.

x-is-backgrounded*string

true when the app sent the request from the background, otherwise false.

Value in

  • "true"
  • "false"
x-is-debug-build*string

true when the app is a debug build, otherwise false. Only debug builds can make simulated development purchases.

Value in

  • "true"
  • "false"
x-nonce?string

A random id, new for every request, such as a lowercase UUID.

x-observer-mode*string

true when the SDK runs in observer mode: another billing integration owns purchases and the SDK only reports them. Otherwise false.

Value in

  • "true"
  • "false"
x-platform*string

The platform the app runs on, such as ios, android or web. Records where a new person signed up.

x-platform-brand?string

The device's manufacturer, such as Apple or Google.

x-platform-device?string

The device's model, such as iPhone15,2; in a browser, its navigator.platform.

x-platform-flavor*string

native in an app, browser in a web page.

Value in

  • "native"
  • "browser"
x-platform-flavor-version?string

The version of the app hosting the SDK; native SDKs send the app's version, the web SDK leaves it out.

x-platform-version?string

The operating system's version, such as 17.4; in a browser, its user agent.

x-preferred-locales?string

The end user's preferred locales, most preferred first, separated by commas, such as en-US,de-DE.

x-sdk*string

The SDK making the request: ios, android, react-native or web. A native SDK driven by another reports the outer one, such as react-native.

Value in

  • "react-native"
  • "web"
  • "ios"
  • "android"
x-sdk-version*string

The version of the SDK making the request, such as 1.4.0.

x-storefront?string

The app store storefront (country) the end user buys from, when the SDK knows it.

Request body

application/json

TypeScript definitions

Use the request body type in TypeScript.

distinctId*string

The distinct id to identify the end user as, such as your own user id. It cannot start with the anonymous prefix vh_anon_.

email?|

The person's email address.

name?|

The person's name.

traits?|

Traits to set on the person; the newest write of each trait wins.

Examples

curl -X POST "https://api.voidhash.com/api/v1/sdk/identify" \  -H "x-distinct-id: vh_anon_7c1e9b2a-4f3d-4e6a-9b8c-2d5f1a0e3c47" \  -H "x-publishable-key: vh_pk_..." \  -H "x-client-bundle-id: com.example.app" \  -H "x-is-backgrounded: true" \  -H "x-is-debug-build: true" \  -H "x-observer-mode: true" \  -H "x-platform: ios" \  -H "x-platform-flavor: native" \  -H "x-sdk: react-native" \  -H "x-sdk-version: 0.0.1-alpha.1" \  -H "Content-Type: application/json" \  -d '{    "distinctId": "user_8231",    "email": "ada@example.com",    "name": "Ada Lovelace"  }'
{  "personId": "person_h7d2k9m4x1c6v8b3n5q0w2e7",  "distinctId": "user_8231",  "email": "ada@example.com",  "name": "Ada Lovelace",  "entitlements": {    "grants": [      {        "perkId": "perk_c4v7b1n9m2x5z8q3w6e0r4t7",        "perkSlug": "premium",        "source": "subscription",        "sourceId": "sub_p9o3i7u1y5t8r2e6w0q4a8s2",        "sourcePersonId": "person_h7d2k9m4x1c6v8b3n5q0w2e7",        "expiresAt": "2026-04-14T09:26:53.000Z",        "status": "active"      }    ]  },  "subscriptions": {    "current": {      "subscriptionId": "sub_p9o3i7u1y5t8r2e6w0q4a8s2",      "productId": "prod_x8k2m5q9v3n7c1z4w6e0r2t5",      "status": "active",      "expiresAt": "2026-04-14T09:26:53.000Z"    },    "history": [      {        "subscriptionId": "sub_p9o3i7u1y5t8r2e6w0q4a8s2",        "productId": "prod_x8k2m5q9v3n7c1z4w6e0r2t5",        "sourcePersonId": "person_h7d2k9m4x1c6v8b3n5q0w2e7",        "status": "active",        "isTrial": false,        "startsAt": "2026-03-14T09:26:53.000Z",        "expiresAt": "2026-04-14T09:26:53.000Z",        "canceledAt": null      }    ]  },  "purchases": {    "history": [      {        "purchaseId": "pur_a3s7d1f5g9h2j6k0l4z8x2c6",        "productId": "prod_x8k2m5q9v3n7c1z4w6e0r2t5",        "providerKey": "2000000123456789",        "sourcePersonId": "person_h7d2k9m4x1c6v8b3n5q0w2e7",        "type": "subscription",        "createdAt": "2026-03-14T09:26:53.000Z"      }    ]  },  "snapshotContext": {    "includedPersonIds": [      "person_h7d2k9m4x1c6v8b3n5q0w2e7"    ],    "migrationJobId": null,    "mode": "persisted"  }}
{  "_tag": "Api/SdkValidationError",  "message": "string"}
{  "_tag": "Api/AuthenticationError",  "cause": "string",  "message": "string"}
{  "_tag": "Api/SdkPersonNotFoundError",  "message": "string"}
{  "_tag": "Api/SdkPersonAlreadyIdentifiedError",  "distinctId": "string"}
{  "_tag": "Api/SdkServiceError",  "cause": "string"}

Response body

application/json

application/json

application/json

application/json

application/json

application/json