Environments
Keep test purchases, keys and webhooks apart from production.
Every purchase Voidhash records belongs to an environment. The environment decides which API keys can read the purchase, which webhooks receive its events, and where it appears in Studio. Test purchases never unlock access in production, so a staging server or a test checkout cannot give anyone paid access in your live app.
Purchase environments
| Environment | What it holds |
|---|---|
| Production | Real purchases from the App Store, Google Play, Stripe live mode and payment sources. |
| Sandbox | Free purchases in a store's own sandbox: App Store sandbox accounts, TestFlight, Apple's App Review and Google Play test purchases. |
| Test | Free purchases your own build or deployment makes: simulated purchases of debug builds in development mode, Stripe test mode, and payment sources reporting with a test key. |
Store sandbox purchases are separate from test purchases because the store decides when a purchase is a sandbox one, and your published app cannot tell them apart: TestFlight runs the same build you ship, and App Review buys with a sandbox account in the build you submit. So by default, store sandbox purchases also unlock access in production apps. You can turn that off, at the cost of App Review no longer unlocking what it buys.
Test purchases never unlock production: anyone can make them without paying. Development mode (React Native, Swift, Kotlin) stands in for the App Store and Google Play, which emulators lack, so its simulated purchases are test purchases too.
API keys
Every API key belongs to production or test, fixed for the life of the key.
| Key | Prefix | Reads |
|---|---|---|
| Production | vh_pk_, vh_sk_ | Production purchases, plus store sandbox purchases while they unlock production apps (the default). |
| Test | vh_pk_test_, vh_sk_test_ | Store sandbox and test purchases. |
Every project has a production publishable key and a test publishable key. Secret keys are created as production or test under Settings → API keys in Studio. What a test secret key reports, such as a payment source's payments, is recorded as test.
Use test keys in staging servers, staging websites and debug builds, and production keys in production. A mobile app you publish to the App Store or Google Play, including TestFlight and Play testing tracks, uses the production publishable key in its release build: TestFlight, App Review and Play test purchases are store sandbox purchases, and they unlock access there by default.
Debug builds in development mode must use the test publishable key. Voidhash refuses simulated purchases made with a production key, since a production key could never read them.
No request header changes what a key reads, so a production key never sees test purchases.
Analytics events
Every analytics event is recorded in the environment of the key that sent it, like a purchase.
Voidhash sets each event's $environment property when the event arrives: test for a test key,
production for a production key. The SDKs send no environment of their own, so a staging website
or a debug build that uses the test publishable key records test page views and events, and a
production key never records test events.
Analytics, ad reports, the event list and experiment results show the events of one environment:
- Production and Sandbox show production events. Store sandbox purchases come from the app you publish, which uses the production key.
- Test shows test events.
So a staging website on the test key stays out of your production visitors, page views, events and experiment results. Events recorded before keys had environments count as production. Through the API, a test key reads test events and a production key production events.
People are not split by environment. Signups and people in ad reports count the people both
environments identified, and tracking health lists every website and app that sends events, staging
included. A staging site that identifies its users with the same IDs as production identifies the
same people, so give staging users IDs of their own, such as with a staging: prefix.
Webhooks
Every webhook endpoint belongs to production or test. Choose its environment when you create it
under Settings → Webhooks, or set environment through the API; the default is production.
- A production webhook receives the purchase events a production key reads: production purchases, and store sandbox purchases while they unlock production apps.
- A test webhook receives store sandbox and test purchase events.
- Events that belong to no purchase, such as
person.deleted, go to every webhook.
Each purchase event's payload says where it came from in its environment field: production,
sandbox or test. See Receive webhooks.
Studio
The environment switcher next to the project name shows one environment at a time:
- Production shows production purchases.
- Sandbox shows store sandbox purchases.
- Test shows test purchases, simulated ones included.
Simulated purchases are turned on or off, and deleted, under Settings → General → Simulated purchases. Deleting removes simulated purchases only, not Stripe test mode or payment-source test purchases.
Analytics and ad reports take the same three environments, production, sandbox and test, and
report production unless you choose another: the revenue of that environment's purchases, and the
events of its keys. See Analytics events.
A typical setup
| Deployment | Key | Webhook |
|---|---|---|
| App Store and Google Play release builds, including TestFlight | Production publishable key | — |
| Production website and backend | Production publishable and secret keys | Production |
| Staging website and backend, Stripe test mode | Test publishable and secret keys | Test |
| Debug builds in development mode | Test publishable key | Test |