Kotlin SDK
Configure the Voidhash Android SDK and look up its client options and methods.
The Kotlin SDK adds entitlements, feature flags, analytics, and observer-mode transaction reporting to native Android apps. Use this page to create the client, set its options, and find the methods you need. Each feature also has its own guide, linked from the section that introduces it.
The initial release is observer-only
SDK-started purchases and hosted paywalls are temporarily unavailable. Google Play transactions are still observed and submitted to Voidhash for revenue analytics, but the SDK never acknowledges or consumes them.
Compatibility
The SDK has the following requirements.
minSdk23.compileSdk34.- AGP 8.9.0, Kotlin 2.0.21, and Java 8 bytecode.
- Play Billing 8.0.0.
Two Gradle modules ship in @voidhash/android. :sdk (com.voidhash.sdk) is the public SDK you
integrate against. :core (com.voidhash.core) is the shared engine it depends on.
Create the client
Create one client and keep it for the lifetime of the app.
import com.voidhash.sdk.Voidhash
import com.voidhash.sdk.VoidhashOptions
val voidhash = Voidhash.configure(
context = applicationContext,
publishableKey = "vh_pk_...",
)The publishable key is safe to include in the app. Never ship vh_sk_... secret keys.
There is no schema argument, because the schema lives on the server and initialize() fetches it.
initialize() connects to Google Play, resolves the schema, reconciles unfinished store
transactions, and starts the analytics queue. Call it once the client exists.
lifecycleScope.launch {
voidhash.initialize()
}It is safe to call initialize() repeatedly. Only the first successful call does work, and
concurrent callers wait for it. A failed call leaves the client uninitialized so you can retry.
Until initialization has succeeded, every method that needs the schema throws VoidhashException
with the code CONFIGURATION_MISSING.
Client options
Pass a VoidhashOptions value to configure to change the defaults.
val voidhash = Voidhash.configure(
context = this,
publishableKey = "vh_pk_...",
options = VoidhashOptions(debug = BuildConfig.DEBUG),
)Each option is described below.
| Option | Default | Description |
|---|---|---|
baseUrl | https://api.voidhash.com | Overrides the API origin for self-hosted deployments. |
ingestUrl | Same origin as baseUrl | Overrides only the analytics origin. |
debug | false | Enables verbose logging and marks requests as debug-build traffic. |
distinctId | Generated anonymous ID | Seeds the initial customer identity. Usually omit it and call identify(). |
enabled | true | Set it to false to ship the SDK fully inert. |
readOnly | true | Forced on while commerce features are unavailable. |
Every method on VoidhashClient is a suspending function, except capture, getDistinctId, and
setReadOnly. The SDK never blocks the caller's thread, and it never posts work back to the main
thread on its own.
Disabled clients
With enabled: false, every method is inert. The SDK makes no requests and opens no billing
connection. getProducts() returns an empty list, and getCurrentPerson() returns null.
Observer mode
The initial release always uses observer mode. Passing readOnly = false or calling
setReadOnly(false) cannot transfer Google Play ownership to Voidhash yet.
Products and transaction reporting
Load the product catalog and restore the customer's existing purchases.
val products = voidhash.getProducts()
voidhash.restorePurchases()Initialization and restore submit observed Google Play transactions to Voidhash without
acknowledging or consuming them. purchase(...) remains in the SDK for a later commerce launch, but
it currently raises READ_ONLY_PURCHASE_NOT_ALLOWED before it touches Play Billing.
After a successful host purchase, call reportTransaction(...) with its store transaction values.
A valid report is persisted before it returns and delivered in the background, so a network or
service outage delays reporting without failing the purchase flow. Use syncPurchases() for
callbacks without transaction values and for restore recovery. Store observers and scans cannot
recover a consumable already finished or consumed by the host.
See Report and restore purchases for callback examples, error
handling, and scan limits.
People and entitlements
Read the current person, identify them when they sign in, and reset the client when they sign out.
voidhash.getDistinctId()
voidhash.identify(externalUserId = "user-123", email = "a@b.co", name = "Ada")
voidhash.setPersonAttributes(mapOf("plan" to "pro"))
val person = voidhash.getCurrentPerson(forceFetch = true)
person?.activePerkIds
voidhash.reset() // Sign out: clears the local identity and cacheThe SDK caches the person snapshot for two days. After five minutes it treats the snapshot as stale
but still serves it from the cache. Pass getCurrentPerson(forceFetch = true) to bypass the cache.
The SDK refreshes the snapshot on its own after purchases, restores, and identity changes.
See Check access and Identify customers for the underlying concepts.
Feature flags
Evaluate the flags you need by key.
val flags = voidhash.getFeatureFlags(listOf("new_onboarding"))
val enabled = flags.firstOrNull { it.key == "new_onboarding" }?.enabled == truePass an empty list to evaluate every flag. See Evaluate feature flags for variants and identity behavior.
Analytics
Capture an event, and call flush() when you need the queue sent right away.
voidhash.capture("checkout_started", mapOf("source" to "paywall"))
voidhash.flush()The SDK batches events, sending a request after 20 events or every 5 seconds. Failed requests are
retried with exponential backoff, so the wait grows after each failure, and the SDK honors the
Retry-After header. Event names beginning with $ are reserved for Voidhash events. See
Capture analytics.
Paywalls
Hosted paywalls are temporarily unavailable. presentPaywall(...) returns false, paywall
resolution returns null, and the SDK performs no network or presentation work.
Shutdown
Call shutdown() when the process is going away for good.
voidhash.shutdown()It flushes analytics and ends the Play Billing connection. Do not call it on every background event.