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
Kotlin SDK
Kotlin quickstart
Display a paywall
Make and restore purchases
Check access
Identify users
Evaluate feature flags
Capture analytics
Groups
Track screens
Development mode
Kotlin SDK reference
Errors
Diagnostic codes
Troubleshooting

Check access

Gate features on the current person's active perks.

Check access by asking whether the current person has an active perk, such as premium. The person's entitlements list each perk they can use and what granted it; see Products and perks and the subscription lifecycle for when access starts and ends.

The SDK decides what your app shows. It can't protect anything a person reaches through your own API: check access on your server for that, with the server library for Node.js, PHP, Go or Rust, or over HTTP.

Gate a feature

hasActivePerk takes the perk's slug from Studio:

suspend fun hasPremium(): Boolean =
    voidhash.getCurrentPerson()?.hasActivePerk("premium") == true

activePerkSlugs lists every perk the person can use right now.

Gate on perks, not subscription status

A subscription status doesn't say which features a product unlocks, and misses access from one-time purchases. Active perks cover both.

Caching and offline behavior

getCurrentPerson() answers from a cache and refreshes behind the read. The snapshot is fresh for 5 minutes and kept for 2 days; after that it's still served, marked expired. With nothing cached, the call waits at most 10 seconds for Voidhash. The SDK refreshes the person after purchases, restores, identify and reset. Pass forceFetch = true to wait for a fresh answer:

val person = voidhash.getCurrentPerson(forceFetch = true)

getCurrentPerson() never throws because Voidhash is unreachable. It keeps serving the last snapshot until Voidhash confirms the person doesn't exist. Use getCurrentPersonState() when you need to know how current the answer is:

val state = voidhash.getCurrentPersonState()
val hasPremium = state.value?.hasActivePerk("premium") == true

if (state.value == null && state.isExpired) {
    // Unknown: nothing is cached and Voidhash couldn't be reached. Don't lock by default.
}
FieldMeaning
valueThe person, or null.
isStalePast the 5-minute refresh window; a refresh is under way.
isExpiredPast the 2-day lifetime, or nothing cached and no answer. Still served.

A null person that isn't expired is a confirmed answer: Voidhash has no person for this identity yet, such as an anonymous visitor who hasn't bought anything.

Read the person

VoidhashPerson holds the person's identity and entitlements:

PropertyMeaning
distinctIdThe current distinct ID.
personIdVoidhash's ID for the person.
email, nameSet through identify or person attributes.
entitlementGrantsEvery grant, active or expired.
currentSubscriptionThe current subscription: productId, status (active, trialing or canceled) and expiresAt, or null. See Statuses.
rawThe full JSON snapshot, including purchase history.

Each EntitlementGrant has these fields:

FieldMeaning
perkSlugThe perk's slug in Studio. Compare this one.
perkIdThe perk's internal ID.
statusactive or expired. isActive is true for active.
sourceWhat granted it: subscription or purchase.
sourceIdThe subscription or purchase that granted it.
expiresAtWhen access ends, as an ISO 8601 string, or null for access that doesn't expire.

Use currentSubscription for account screens, such as the current plan and its renewal date.

Environments

The publishable key the client uses decides which purchases unlock perks. With the production key (vh_pk_…), production purchases count, plus store sandbox purchases such as Google Play test purchases while they unlock production apps. With the test key (vh_pk_test_…), store sandbox, simulated and test mode purchases count, never production ones. Use the test key in debug builds and the production key in release builds.

Next steps

  • Identify users so access follows them across devices.
  • Make and restore purchases.
  • Check access from your backend with Node.js, PHP, Go, Rust or over HTTP
  • Troubleshooting.

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

PreviousMake and restore purchasesNextIdentify users

On this page

Gate a featureCaching and offline behaviorRead the personEnvironmentsNext steps