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
A project secret key: vh_sk_... for production, vh_sk_test_... for test. Keep it on your servers.
In: header
Path parameters
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.
An id the caller chooses for the action; repeating an action with the same id applies it once.
1 <= lengthThe 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"
Whether targetId names a purchase or a subscription.
Value in
- "subscription"
- "purchase"
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
| Status | type | code | When |
|---|---|---|---|
| 400 | invalid_request | action_not_allowed | For an action the target does not support. |
| 404 | not_found | sandbox_target_not_found | For 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
Something wrong or missing on this page? Tell us by email or on Discord.