High-Level Flow Options

Learn the different ways your game backend can work with Stash Pay. Understand how ConfirmPayment, PURCHASE_SUCCEEDED webhooks, and GetPaymentEvent fit into your architecture so you can choose the flow that best matches your game's rules and reward experience.

This article walks through three Stash Pay integration patterns and when to use each one, based on:

  • Your game-specific technical requirements (inventory limits, multi-client locking)
  • Your backend architecture (async/event-based vs. synchronous)
  • Your preferred in-game reward-granting behavior

Before you start, you need an API key generated in Stash Studio, our developer portal.

If you don't have access to Stash Studio, contact the Stash team. They'll set up your game instance and enable payment processing for you.

Initial Setup

Set up Stash Pay instance

To set up Stash Pay, contact the Stash team. After onboarding, you'll receive access to Stash Studio, our developer portal. Your game instance (including payment processing) will be created for you so you can begin the integration.

Get your API key

Once you have your Stash Studio instance all set up, the only prerequisite is creating your first API key. You'll use this key to call Stash Pay API endpoints from your game backend. Specifically, you'll need an Ingress API key for the GetPaymentEvent endpoint, and an Egress API key for the ConfirmPayment endpoint.

Core Checkout Flow (Common to All Options)

All three options share the same basic checkout flow:

Requesting Checkout

From your game client or backend, request a checkout session via the Stash API. Provide:

  • The player identifier (e.g. your internal player ID)
  • The items or bundles the player wants to purchase

Get Checkout URL

Receive a customized checkout URL and a unique checkout/intent ID from Stash. Store this ID on your backend, associated with the player and the pending purchase.

Show Checkout

Display the checkout to the player via redirect, popup, or in-app browser. The player reviews the purchase and completes payment using the configured payment methods.

Stash pre-authorizes the payment, then proceeds according to the integration pattern you choose.

Choosing Your Stash Pay Flow

You can choose between three main patterns:

  1. ConfirmPayment
  2. PURCHASE_SUCCEEDED webhook
  3. GetPaymentEvent

Use the following criteria to decide which flow (or combination) fits your game best.

1. Do you need inventory management or purchase locks?

Use this criterion if your game has stricter rules around:

  • Per-player inventory limits (e.g. cap on how many times a bundle can be purchased)
  • Locking purchases across multiple game clients/devices
  • Other validation that must happen before a purchase is finalized

Best fit: ConfirmPayment

Direction: Stash → Game (your backend exposes this endpoint).

With ConfirmPayment, Stash calls your backend before finalizing the charge. This gives your game server a chance to:

  • Validate the purchase (inventory, caps, locks)
  • Optionally grant rewards as part of that validation
  • Approve or reject the transaction

Typical flow with ConfirmPayment

Player completes checkout.

Stash sends a ConfirmPayment request to your backend.

Your backend applies your game rules (inventory/locks/eligibility) and optionally grants rewards immediately.

Your backend responds with Approve (Stash finalizes the charge) or Reject (Stash cancels the charge).

Choose this if your game can't safely finalize a purchase without the backend being in the loop first.

2. What's your preferred Verification & Granting behavior?

Use this criterion to decide when and how rewards should be granted:

  • Pre-purchase: Verify and grant before the charge is finalized
  • Post-purchase, delayed: Grant later via async processing
  • Post-purchase, immediate: Grant as soon as the purchase is confirmed

Option A: Pre-purchase granting with ConfirmPayment

When to use:

  • You need to verify inventory and locks and grant rewards before the charge is finalized.
  • You want the player to see rewards as "already granted" when the purchase finishes.

How it works:

  1. Stash calls your ConfirmPayment endpoint.
  2. Your backend validates the purchase and grants rewards.
  3. Your backend approves the payment.
  4. Stash finalizes the charge.

Option B: Post-purchase, delayed via PURCHASE_SUCCEEDED webhook

When to use:

  • Your backend processes events asynchronously.
  • It's acceptable for rewards to appear a bit later in the game.

How it works:

  1. Stash finalizes the payment.
  2. Stash sends a PURCHASE_SUCCEEDED webhook.
  3. Your backend processes the event and grants rewards later.

Option C: Post-purchase, immediate via GetPaymentEvent

When to use:

  • You want the client to show rewards immediately after purchase.
  • You don't need pre-purchase verification beyond what Stash already does.
  • You prefer your server to actively query Stash.

How it works:

  1. Player completes checkout.
  2. Your backend calls GetPaymentEvent.
  3. If the purchase succeeded, your backend grants rewards and returns the updated player state to the client.

You can also combine these patterns (for example, using ConfirmPayment for validation and GetPaymentEvent for client-side confirmation), depending on your game's needs.

3. What's your current backend architecture? (event-based vs synchronous)

Use this criterion if your backend is primarily:

  • Async/event-driven (queues, workers, background jobs), or
  • Synchronous/request–response (client expects an immediate result from the server)

Best fit for async/event-driven: PURCHASE_SUCCEEDED webhook
Best fit for synchronous: GetPaymentEvent

PURCHASE_SUCCEEDED webhook (async)

Direction: Stash → Game (your backend exposes a webhook endpoint).

This fits an event-driven architecture where your backend consumes events and processes them asynchronously.

Typical flow:

  1. Player completes checkout.
  2. Stash finalizes the payment.
  3. Stash sends a PURCHASE_SUCCEEDED webhook to your backend.
  4. Your backend:
    • Consumes the event (e.g. via a queue or worker).
    • Runs your game logic and grants rewards.
    • Updates your own systems (logs, analytics, CRM, etc.).

Choose this if you're comfortable with rewards appearing slightly later in the game, and you already use webhooks and background workers to process external events.

GetPaymentEvent (synchronous)

Direction: Game → Stash (your backend calls this endpoint).

This fits a synchronous pattern where the client expects a definitive answer right after purchase. See the GetPaymentEvent API Reference for request/response details.

Typical flow:

  1. Player completes checkout.
  2. Your backend (or client via your backend) calls GetPaymentEvent with the purchase ID.
  3. Stash returns the final status of the payment.
  4. If successful, your backend grants rewards and returns an updated state to the client.

Choose this if you want to avoid webhooks and keep control on the game server side, or if your client needs a "final answer" immediately and your backend is already designed for synchronous calls.

Handling Failures and Edge Cases

Regardless of which pattern you choose:

Idempotency

Make your reward-granting logic idempotent by purchase ID so retries (from webhooks or polling) never grant rewards twice.

Timeouts and retries

  • For ConfirmPayment, define clear behavior when your backend is slow or unavailable (e.g. reject, retry, or show a recoverable error in-game).
  • For webhooks, implement retry handling and signature verification as recommended in the Webhook Retries guide.
  • For GetPaymentEvent, handle transient failures (e.g. retry with backoff) and show appropriate messaging to the player.

How is this guide?