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
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 sandbox settings
Update sandbox settings
Retrieve a person's sandbox state
Simulate a store event
Delete sandbox data

Simulate a store event

Simulates a store event on a sandbox purchase or subscription: a purchase can be refunded or revoked; a subscription can expire, be revoked, renew or enter a three-day grace_period.

The person's access changes at once; webhooks and analytics follow in the background. Repeating an actionId applies the action once.

Guide: Simulate renewals, expiry and refunds

POST
/api/v1/projects/{projectId}/sandbox/actions

Authorization

AuthorizationBearer <token>

A project secret key: vh_sk_... for production, vh_sk_test_... for test. Keep it on your servers.

In: header

Path parameters

projectId*string

The project's id, proj_.... A secret key works only in the project it belongs to.

Request body

application/json

TypeScript definitions

Use the request body type in TypeScript.

actionId*string

An id the caller chooses for the action; repeating an action with the same id applies it once.

Length1 <= length
action*string

The store event: refund or revoke a purchase; renew a subscription for another billing period, expire it, revoke it, or start a three-day grace_period as after a failed renewal.

Value in

  • "expire"
  • "revoke"
  • "renew"
  • "refund"
  • "grace_period"
targetType*string

Whether targetId names a purchase or a subscription.

Value in

  • "subscription"
  • "purchase"
targetId*string

The id of the sandbox purchase (pur_...) or subscription (sub_...).

Examples

curl -X POST "https://api.voidhash.com/api/v1/projects/proj_tz4a98xxat96iws9zmbrgj3a/sandbox/actions" \  -H "Authorization: Bearer vh_sk_..." \  -H "Content-Type: application/json" \  -d '{    "actionId": "renew-2026-03-14-1",    "action": "renew",    "targetType": "subscription",    "targetId": "sub_d4f8g2h6j0k3l7z1x5c9v3b7"  }'
{  "actionId": "renew-2026-03-14-1",  "action": "renew",  "targetType": "subscription",  "targetId": "sub_d4f8g2h6j0k3l7z1x5c9v3b7"}
{  "error": {    "type": "invalid_request",    "code": "action_not_allowed",    "message": "A sandbox purchase supports refund, revoke, not renew.",    "param": "action"  }}
{  "error": {    "type": "unauthenticated",    "code": "invalid_api_key",    "message": "This secret key is not valid."  }}
{  "error": {    "type": "permission_denied",    "code": "permission_denied",    "message": "Insufficient permissions."  }}

{  "error": {    "type": "not_found",    "code": "sandbox_target_not_found",    "message": "This project has no sandbox subscription sub_d4f8g2h6j0k3l7z1x5c9v3b7.",    "param": "targetId"  }}

{  "error": {    "type": "internal",    "code": "internal_error",    "message": "Something went wrong on our side. Try again, and contact support with the Request-Id header if it keeps failing."  }}

Response body

application/json

application/json

application/json

application/json

application/json

application/json

Errors

StatustypecodeWhen
400invalid_requestaction_not_allowedFor an action the target does not support.
404not_foundsandbox_target_not_foundFor a target that is not a sandbox purchase or subscription of the project.

It can also fail with the errors every operation shares, such as unauthenticated; see Errors.

More in Sandbox

  • Retrieve sandbox settings GET
  • Update sandbox settings PATCH
  • Retrieve a person's sandbox state GET
  • Delete sandbox data DELETE

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

PreviousRetrieve a person's sandbox stateNextDelete sandbox data

On this page

AuthorizationPath parametersRequest bodyExamplesResponse bodyErrorsMore in Sandbox