Integrating Stash Pay
Learn how to integrate Stash Pay into your game or app with minimum setup. This guide covers creating checkout links, displaying checkouts in browser or in-app, and handling webhook events for secure payment processing.
This guide explains how to integrate Stash Pay using the basic setup: creating checkout links, showing the checkout to players, and processing purchase events.
The video below provides a quick walkthrough of the integration flow.
Apple Pay and Google Pay do not work in the test environment without individual setup. Both require sandbox accounts. Contact your Stash representative to provision them for your test environment if needed.
Create a checkout link
To create a checkout session, send a POST request from your backend to the /sdk/server/checkout_links/generate_quick_pay_url endpoint.
Please check out the full API reference to see all the payload options.
Checkout link request
Here's a sample payload for creating a checkout link:
{
"item": {
"id": "",
"pricePerItem": "",
"quantity": 1,
"imageUrl": "",
"name": "",
"description": ""
},
"user": {
"id": "",
"validatedEmail": "",
"profileImageUrl": "",
"displayName": "",
"regionCode": "",
"platform": "UNDEFINED"
},
"transactionId": "",
"regionCode": "",
"currency": ""
}| Parameter | Type | Description |
|---|---|---|
| item | object | The item being purchased. Fields: - id: Unique identifier for the item.- pricePerItem: Price per item in the smallest currency unit (e.g., cents).- quantity: Number of items being purchased.- imageUrl: Optional image representing the item.- name: Name of the item.- description: Short description of the item. |
| user | object | Information about the purchasing user. Fields: - id: Unique user ID (from your system).- validatedEmail: (optional) Email address if available and validated.- profileImageUrl: (optional) Link to the user's avatar image.- displayName: User display name.- regionCode: (optional) User's region code for localization.- platform: Platform string, e.g., IOS, ANDROID, or UNDEFINED. |
| transactionId | string | Unique transaction identifier generated by your backend for idempotency and tracking. |
| regionCode | string | (optional) Region/country code for payment localization (e.g., "US"). |
| currency | string | ISO 4217 currency code for the transaction (e.g., "USD", "EUR"). |
Checkout link response
If your request succeeds, you will receive a checkout URL that you can present to the user using any of the methods described below.
{
"url": "https://store.example.com/order/abc123",
"id": "abc123",
"regionCode": "US"
}Authentication
Authenticate calls to generate_quick_pay_url by signing the request body with your ingress secret and including the signature in the x-stash-hmac-signature header. Your ingress secret is distinct from the egress key used to verify Stash's outbound requests. Both are in Studio → Project Settings → API Keys as base64-encoded values; base64-decode before use as the HMAC key.
x-stash-hmac-signature: v1;<appId>;<unixMillisTimestamp>;<base64-hmac>| Field | Description |
|---|---|
v1 | Protocol version |
<appId> | Your immutable App ID (Studio → Project Settings → General) |
<unixMillisTimestamp> | Request timestamp in Unix milliseconds |
<base64-hmac> | Standard base64-encoded HMAC-SHA256 signature |
The signature covers "<unixMillisTimestamp>." + <body>, where <body> is the exact JSON bytes you POST. Sign what you transmit — Stash verifies against the bytes received. Requests where <unixMillisTimestamp> is more than 5 minutes from the server clock are rejected.
For Node.js, Python, and Go implementation code, see API Keys → HMAC Signing.
Shops and API keys created before 2026-08-15 can still use X-Stash-Api-Key: <secret> instead. Keys created on or after 2026-08-15 must use versioned HMAC.
Displaying the checkout
The simplest option is to open the checkout URL directly in a browser on the user's device. For in-app presentation with native drawers, modals, and callbacks, follow the platform-specific integration guide for your stack.
Web Apps & WebGL
React component, vanilla API, and UMD script-tag integration.
Native Apps (iOS / Android)
Card, modal, and browser presentation using the Stash Native SDK.
Unity Integration
Present checkout from Unity projects using the Stash Unity package.
Unreal Engine Integration
Present checkout from Unreal Engine projects using the Stash plugin.
Processing Purchase
Once a player completes checkout, your system must process the event to grant items. Stash supports three patterns depending on your game's requirements, always server-side, never on the client.
The three differ mainly in when they fire relative to the charge, and only one of them lets your server reject a purchase:
| Pattern | When it fires | Direction | Can your server reject? | Best for |
|---|---|---|---|---|
ConfirmPayment | Before the charge is captured | Stash calls your server | Yes. See the warning in that tab. | Inventory limits, purchase caps, multi-client locking |
PURCHASE_SUCCEEDED webhook | After the payment completes | Stash calls your server | No | Backends that process events asynchronously through queues, workers, or jobs |
GetPaymentEvent | After the payment completes, when you ask for it | Your server calls Stash | No | Showing rewards in the client immediately after purchase |
This is an integration-time choice, not a runtime one. Which delivery mechanism a shop uses is fixed when the shop is configured, not selected per purchase, so a single shop uses one of these patterns rather than switching between them. Pick the row that matches your backend, and see the High-Level Flow Options guide for the full sequence of each.
Async post-purchase. Stash sends your backend a PURCHASE_SUCCEEDED webhook after the payment completes.
Best for: Backends that process events asynchronously (queues, workers, background jobs), where it's acceptable for rewards to appear a bit later in the game.
Configure your webhook endpoint in Stash Studio and implement a listener that verifies the signature and grants rewards. See the webhook guides for full implementation details:
- Webhooks Overview: configure webhooks in Stash Studio
- Webhook Listener: create a listener and verify signatures
- Webhook List: all event types and payload structures
- Webhook Retries: retry behavior and idempotent handlers
Testing your integration
To test your Stash Pay integration, use test card numbers in the Stash test environment. These cards allow you to complete transactions safely, as no real charges are created, making repeated testing risk-free.
Environment Requirements:
- Test/Development/Staging: Use test cards only. Test cards function in test environments and will be rejected in production.
- Production: Use real, live payment cards only. Real cards are accepted for production transactions and will be rejected in test environments.
- Apple Pay and Google Pay are not available in the test environment. These payment methods require live mode and will not function when testing.
Testing Tools
Link Generator: Use the Link Generator in Stash Studio to quickly generate and test checkout links without writing code. The Link Generator allows you to:
How is this guide?
High-Level Flow
Learn how Stash Pay's purchase flow works and discover three integration patterns for granting purchases based on your existing infrastructure.
About Subscriptions
Learn about Stash Subscriptions - a recurring billing system for games that enables battle passes, VIP memberships, and premium tiers with automatic renewals and flexible billing periods.