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

Development mode

Test purchases in debug builds with a simulated store, without Google Play setup.

Development mode lets a debug build buy from a simulated store while Voidhash processes the purchases for real. Use it to test your purchase screen, paywalls and access checks on any device or emulator before you connect Google Play.

Simulated purchases are recorded in the test environment, never unlock production access and never count toward production revenue. They need the project's test publishable key (vh_pk_test_...): Voidhash refuses simulated purchases made with a production key.

Turn it on

Give your products a billing duration in Studio; it sets the simulated renewal and expiry dates. Then set dev and the test key for debug builds:

App.kt
val voidhash = Voidhash.configure(
    context = this,
    publishableKey = if (BuildConfig.DEBUG) "vh_pk_test_..." else "vh_pk_...",
    options = VoidhashOptions(dev = BuildConfig.DEBUG),
)

The SDK honors dev only in debuggable builds; release builds always use Google Play. A purchase shows a Test purchase confirmation sheet instead of Google Play's, waits briefly, and sends the purchase to Voidhash. The SDK then refreshes the person, so hasActivePerk sees the new perk.

Simulated purchases go through purchase(...) and paywalls like real ones, so observer mode refuses them with READ_ONLY_PURCHASE_NOT_ALLOWED. A product without development data fails with PRODUCT_NOT_FOUND.

Test prices

Simulated purchases use fixed USD prices:

ProductPrice
Weekly subscription$4.99
Monthly subscription$9.99
Quarterly subscription$24.99
Six-month subscription$39.99
Annual subscription$49.99
Non-consumable$19.99
Consumable$4.99

A subscription without a billing duration is simulated as monthly.

Simulate renewals and refunds

Move a simulated subscription through its lifecycle with the CLI. Name the person by distinct ID or email:

voidhash sandbox view user_123
voidhash sandbox renew user_123
voidhash sandbox expire user_123
voidhash sandbox grace-period user_123
voidhash sandbox refund user_123
voidhash sandbox revoke user_123

The CLI isn't published to a package registry yet. The same actions work through the MCP server and the HTTP API; see Simulate renewals, expiry and refunds.

Add the product's slug when the person has several. voidhash sandbox reset deletes every simulated purchase in the project; production, store sandbox and Stripe test data are untouched. If debug builds can't simulate purchases, turn on Enable simulated purchases in Settings → General, or run voidhash settings set sandbox-purchasing on.

In Studio, switch the environment to Test to see simulated purchases.

Next steps

  • Test purchases (Help center) with Google Play license testers.
  • Make and restore purchases.
  • Connect Google Play (Help center) before release.

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

PreviousTrack screensNextKotlin SDK reference

On this page

Turn it onTest pricesSimulate renewals and refundsNext steps