Stash Webhooks

Webhook List

Comprehensive list of all webhook events that Stash can send to your backend, including event types, triggers, payload structures, and detailed examples for each webhook type across Stash products.

This page contains a comprehensive list of all webhook events that Stash can send to your backend. Each webhook is triggered by specific user actions or system events.

Product-specific events: Some events are specific to Stash Pay or Stash Webshop. See the Stash Pay integration guide or Stash Webshop integration guide for product-specific webhook details.

Required Events

These events are essential for purchase processing and should always be subscribed to:

PURCHASE_SUCCEEDED

Products: Stash Pay, Stash Webshop

Sent when a purchase is successfully completed. This is the primary event for granting items to players.

When to use: Always subscribe to this event to grant items to players after successful payment.

Key Fields:

  • orderId: Order identifier
  • userId: External user ID
  • items: Array of purchased items with quantities and prices
  • total: Total amount paid
  • currency: Currency code (e.g., "USD", "EUR")
  • source: Indicates the source product ("StashPay" or "Cart" for Webshop)

Optional Events

These events are optional and primarily used for analytics, user behavior tracking, and marketing purposes:

Stash Webshop Events

The following events are specific to Stash Webshop:

MUTATE_CART

Product: Stash Webshop only

Sent when a user adds, removes, or modifies items in their cart.

Use Case: Track cart abandonment, analyze shopping behavior, trigger marketing campaigns.

VIEW_ITEM

Product: Stash Webshop only

Sent when a user views an item (debounced to once per 100 seconds per item).

Use Case: Product interest tracking, recommendation algorithms.

VIEW_CHECKOUT_PAGE

Product: Stash Webshop only

Sent when a user views the checkout page.

Use Case: Track checkout page visits, identify drop-off points.

VIEW_PRODUCT_DETAIL_PAGE

Product: Stash Webshop only

Sent when a user views a product detail page.

Use Case: Product interest tracking, content engagement metrics.

CART_BUTTON_CLICK

Product: Stash Webshop only

Sent when a user clicks the cart button/icon.

Use Case: Track cart interactions, shopping behavior analysis.

Shared Events

The following events can be sent by both Stash Pay and Stash Webshop:

CREATE_PAYMENT_INTENT

Products: Stash Pay, Stash Webshop

Sent when a payment intent is created (user initiates checkout).

Use Case: Track checkout initiation, payment method selection analytics.

FREE_ITEM_REDEEMED

Products: Stash Pay, Stash Webshop

Sent when a user redeems a free item (promotional items, rewards, etc.).

Use Case: Track promotional campaign effectiveness, user engagement.

Available webhooks

Event TypeProductsDescriptionTrigger
PURCHASE_SUCCEEDEDPay, WebshopFired when a purchase is successfully completedWhen a user completes a purchase transaction
MUTATE_CARTWebshopFired when items are added, removed, or modified in cartWhen cart contents change (add/remove items, quantity changes)
VIEW_ITEMWebshopFired when a user views a specific itemWhen a user visits an item page or views item details
CREATE_PAYMENT_INTENTPay, WebshopFired when a payment process is initiatedWhen user starts checkout process or opens payment flow
FREE_ITEM_REDEEMEDPay, WebshopFired when a user redeems a free itemWhen a free item is claimed or redeemed
VIEW_CHECKOUT_PAGEWebshopFired when user visits the checkout pageWhen checkout page is loaded
VIEW_PRODUCT_DETAIL_PAGEWebshopFired when user views product detailsWhen product detail page is accessed
CART_BUTTON_CLICKWebshopFired when cart-related buttons are clickedWhen user interacts with cart buttons

Payload structure

All webhooks follow a consistent structure with a base webhook object:

Base Webhook Structure
{
  "type": "EVENT_TYPE",
  "eventData": {
    // Event-specific payload data
  }
}

Detailed payload examples

PURCHASE_SUCCEEDED

Triggered when a purchase is successfully completed.

Note: The source field will be "StashPay" for purchases made through Stash Pay, or "Cart" for purchases made through Stash Webshop.

Purchase Succeeded Event (Stash Pay example)
{
  "type": "PURCHASE_SUCCEEDED",
  "purchaseSucceeded": {
    "timeMillis": 1640995200000,
    "orderId": "order_abc123",
    "checkoutLinkId": "checkout_xyz789",
    "currency": "USD",
    "userId": "user_123",
    "items": [
      {
        "id": "item_456",
        "quantity": 2,
        "price": "9.99",
        "metadata": {
          "category": "weapons",
          "rarity": "legendary"
        }
      }
    ],
    "tax": "1.50",
    "total": "21.48",
    "taxDetails": {
      "items": [
        {
          "label": "Sales Tax",
          "isInclusive": false,
          "amount": "1.50",
          "percentage": "7.5",
          "country": "US",
          "state": "CA"
        }
      ]
    },
    "emailMarketingOptIn": true,
    "regionCode": "US",
    "source": "StashPay",
    "ipAddress": "192.168.1.1"
  }
}

MUTATE_CART

Triggered when cart contents are modified.

Mutate Cart Event
{
  "type": "MUTATE_CART",
  "mutateCart": {
    "cartId": "cart_789",
    "timeMillis": 1640995200000,
    "userId": "user_123",
    "items": [
      {
        "id": "item_456",
        "quantity": 3
      },
      {
        "id": "item_789",
        "quantity": -1
      }
    ],
    "regionCode": "US",
    "source": "Cart",
    "ipAddress": "192.168.1.1"
  }
}

VIEW_ITEM

Triggered when a user views an item.

View Item Event
{
  "type": "VIEW_ITEM",
  "viewItem": {
    "userId": "user_123",
    "itemId": "item_456",
    "regionCode": "US"
  }
}

CREATE_PAYMENT_INTENT

Triggered when payment process is initiated.

Note: The source field will be "StashPay" for Stash Pay or "Cart" for Stash Webshop.

Create Payment Intent Event
{
  "type": "CREATE_PAYMENT_INTENT",
  "openPayment": {
    "cartId": "cart_789",
    "userId": "user_123",
    "items": [
      {
        "id": "item_456",
        "quantity": 2
      }
    ],
    "source": "StashPay"
  }
}

FREE_ITEM_REDEEMED

Triggered when a free item is redeemed.

Free Item Redeemed Event
{
  "type": "FREE_ITEM_REDEEMED",
  "freeItemRedeemed": {
    "userId": "user_123",
    "itemId": "item_free_001",
    "ipAddress": "192.168.1.1",
    "metadata": {
      "promotionId": "summer_promo",
      "redeemCode": "SUMMER2024"
    }
  }
}

VIEW_CHECKOUT_PAGE

Triggered when checkout page is viewed.

View Checkout Page Event
{
  "type": "VIEW_CHECKOUT_PAGE",
  "viewCheckoutPage": {
    "userId": "user_123",
    "regionCode": "US"
  }
}

VIEW_PRODUCT_DETAIL_PAGE

Triggered when product details are viewed.

View Product Detail Page Event
{
  "type": "VIEW_PRODUCT_DETAIL_PAGE",
  "viewProductDetailsPage": {
    "userId": "user_123",
    "itemId": "item_456",
    "regionCode": "US"
  }
}

CART_BUTTON_CLICK

Triggered when cart buttons are clicked.

Cart Button Click Event
{
  "type": "CART_BUTTON_CLICK",
  "sendCartButtonClick": {
    "userId": "user_123",
    "regionCode": "US"
  }
}

Common fields

Several fields appear across multiple webhook types:

  • userId: The external user identifier from your system
  • regionCode: Unicode CLDR region code (e.g., "US", "FR") based on user location
  • ipAddress: User's IP address when the event occurred
  • timeMillis: Timestamp in milliseconds since Unix epoch

Subscription Events (v2)

Subscription webhooks use a v2 payload format with lowercase dot-notation event types, unlike the v1 format used by purchase and webshop events above.

Subscription events notify your system of subscription lifecycle changes. See the Subscriptions guide for full integration details.

Available subscription events

Event TypeDescriptionTrigger
subscription.createdNew subscription createdPlayer completes subscription checkout
subscription.updatedSubscription changedPlan or status was modified
subscription.canceledSubscription canceledPlayer cancels their subscription
subscription.reactivatedSubscription reactivatedCanceled subscription was reactivated
subscription.expiredSubscription expiredSubscription reached terminal state
subscription.payment_failedPayment failedRenewal payment attempt failed
subscription.payment_succeededPayment succeededRenewal payment processed successfully

v2 Payload structure

Subscription webhooks use a different structure from v1 events:

v2 Webhook Structure
{
  "type": "subscription.event_name",
  "data": {
    // Subscription object
  }
}

subscription.created

Triggered when a new subscription is created.

subscription.created
{
  "type": "subscription.created",
  "data": {
    "id": "sub_xyz789",
    "external_account_id": "player_123",
    "plan_id": "plan_abc123",
    "status": "active",
    "period": {
      "value": 1,
      "unit": "month"
    },
    "trial_end": "2024-02-01T00:00:00Z",
    "access_end_date": "2024-03-01T00:00:00Z",
    "current_period_end": "2024-03-01T00:00:00Z",
    "next_billing_date": "2024-03-01T00:00:00Z",
    "cancel_at_period_end": false,
    "canceled_at": null,
    "created_at": "2024-01-01T00:00:00Z"
  }
}

subscription.updated

Triggered when a subscription's plan or status changes.

subscription.updated
{
  "type": "subscription.updated",
  "data": {
    "id": "sub_xyz789",
    "external_account_id": "player_123",
    "plan_id": "plan_abc123",
    "status": "active",
    "period": {
      "value": 1,
      "unit": "month"
    },
    "trial_end": null,
    "access_end_date": "2024-04-01T00:00:00Z",
    "current_period_end": "2024-04-01T00:00:00Z",
    "next_billing_date": "2024-04-01T00:00:00Z",
    "cancel_at_period_end": false,
    "canceled_at": null,
    "created_at": "2024-01-01T00:00:00Z"
  }
}

subscription.canceled

Triggered when a player cancels their subscription.

subscription.canceled
{
  "type": "subscription.canceled",
  "data": {
    "id": "sub_xyz789",
    "external_account_id": "player_123",
    "plan_id": "plan_abc123",
    "status": "canceled",
    "period": {
      "value": 1,
      "unit": "month"
    },
    "trial_end": null,
    "access_end_date": "2024-03-01T00:00:00Z",
    "current_period_end": "2024-03-01T00:00:00Z",
    "next_billing_date": "2024-03-01T00:00:00Z",
    "cancel_at_period_end": true,
    "canceled_at": "2024-02-15T14:30:00Z",
    "created_at": "2024-01-01T00:00:00Z"
  }
}

subscription.reactivated

Triggered when a canceled subscription is reactivated before expiration.

subscription.reactivated
{
  "type": "subscription.reactivated",
  "data": {
    "id": "sub_xyz789",
    "external_account_id": "player_123",
    "plan_id": "plan_abc123",
    "status": "active",
    "period": {
      "value": 1,
      "unit": "month"
    },
    "trial_end": null,
    "access_end_date": "2024-03-01T00:00:00Z",
    "current_period_end": "2024-03-01T00:00:00Z",
    "next_billing_date": "2024-03-01T00:00:00Z",
    "cancel_at_period_end": false,
    "canceled_at": null,
    "created_at": "2024-01-01T00:00:00Z"
  }
}

subscription.expired

Triggered when a subscription reaches its terminal state.

subscription.expired
{
  "type": "subscription.expired",
  "data": {
    "id": "sub_xyz789",
    "external_account_id": "player_123",
    "plan_id": "plan_abc123",
    "status": "expired",
    "period": {
      "value": 1,
      "unit": "month"
    },
    "trial_end": null,
    "access_end_date": "2024-03-01T00:00:00Z",
    "current_period_end": "2024-03-01T00:00:00Z",
    "next_billing_date": "2024-03-01T00:00:00Z",
    "cancel_at_period_end": true,
    "canceled_at": "2024-02-15T14:30:00Z",
    "created_at": "2024-01-01T00:00:00Z"
  }
}

subscription.payment_failed

Triggered when a renewal payment attempt fails. The subscription enters past_due status and Stash will retry.

subscription.payment_failed
{
  "type": "subscription.payment_failed",
  "data": {
    "id": "sub_xyz789",
    "external_account_id": "player_123",
    "plan_id": "plan_abc123",
    "status": "past_due",
    "period": {
      "value": 1,
      "unit": "month"
    },
    "trial_end": null,
    "access_end_date": "2024-03-03T00:00:00Z",
    "current_period_end": "2024-03-01T00:00:00Z",
    "next_billing_date": "2024-03-02T00:00:00Z",
    "cancel_at_period_end": false,
    "canceled_at": null,
    "created_at": "2024-01-01T00:00:00Z"
  }
}

subscription.payment_succeeded

Triggered when a renewal payment is processed successfully.

subscription.payment_succeeded
{
  "type": "subscription.payment_succeeded",
  "data": {
    "id": "sub_xyz789",
    "external_account_id": "player_123",
    "plan_id": "plan_abc123",
    "status": "active",
    "period": {
      "value": 1,
      "unit": "month"
    },
    "trial_end": null,
    "access_end_date": "2024-04-01T00:00:00Z",
    "current_period_end": "2024-04-01T00:00:00Z",
    "next_billing_date": "2024-04-01T00:00:00Z",
    "cancel_at_period_end": false,
    "canceled_at": null,
    "created_at": "2024-01-01T00:00:00Z"
  }
}

Subscription object fields

FieldTypeDescription
idstringUnique identifier for the subscription
external_account_idstringIdentifier for the player/user
plan_idstringPlan identifier
statusstringactive, past_due, canceled, or expired
periodobjectBilling period with value (integer) and unit (day/week/month/year)
trial_endstring (nullable)ISO 8601 timestamp when trial ends
access_end_datestringISO 8601 timestamp when access expires
current_period_endstringISO 8601 timestamp for current period end
next_billing_datestringISO 8601 timestamp for next billing attempt
cancel_at_period_endbooleanWhether cancellation is scheduled
canceled_atstring (nullable)ISO 8601 timestamp when canceled
created_atstringISO 8601 timestamp when created

How is this guide?