Skip to content
  • Our Product
    • Namazu Elements
      • What is Elements?
      • Why open source?
      • Docs
        • Namazu Elements in Five Minutes or Less
        • RESTful APIs Library
        • Security Model
        • Accessing the Web UI (CMS)

    Our Product

    A logomark with three layered rhombuses adorning the lettermark that says Elements in bold all-caps sans-serif letters.
    • What is Namazu Elements? Discover our easy-to-use backend network solution built for online games. Rapidly enables full-scale multiplayer games or online solo adventures.
    • Why open source? Is there a truly open source server backend for connected games? There is now. Download and run a local copy of Namazu Elements and try it for yourself.
    Download Namazu Elements

    Get started

    • Quick start Read our Elements 5-minute quick start guide
    • Documentation Read our developer docs for learning more about Elements
    • RESTful APIs A full list of core API specs for working with the Elements framework
    • Security An overview of the server-authoritative security model of Elements
    • Accessing the CMS Manage your game with ease via the Namazu Elements CMS.

    Co-development Reimagined

    • Best real-time game backends in 2026 If you're researching an alternative to your current backend solution, we've prepared a report of all of the backend solutions on the market in 2026 and how Namazu Elements compares.
      Co-dev

    Recent Posts

    • The watercolor-styled Namazu Studios logo over a giant namazu lurking in the depth
      Namazu Studios Featured in San Diego Business Journal
      22 Sep 2025 Press
    • Namazu Elements 3.1 Released – Service Layer Fixes, Secure APIs, and Steam Bug Fix
      22 Apr 2025 Release Notes
  • Case Studies
  • About Us
  • News
  • Services
  • Book a call
namazu-studios-logo
Book a call
Popular Search Roblox

Getting Started

  • Namazu Elements in Five Minutes or Less
  • Overview
  • Accessing the Web UI (CMS)
  • CMS Feature Overview

Fundamentals

  • Why You Need a Server (and What “Authoritative” Means)
  • Elements as a Game Runtime
  • Where Your Authoritative Code Runs
  • Lifecycles and Flows

General Concepts

  • Custom Elements
  • Data Models
  • Security Model
  • N-Tier Architecture

Namazu Elements Core Features

  • Email Service
  • Applications
  • Sessions
  • Users and Profiles
  • Digital Goods
  • Progress and Missions
  • Progress and Missions (3.4+)
  • Leaderboards
  • Matchmaking – Comprehensive Guide
  • Friends
  • Followers
  • Product Bundles and SKUs
  • Item Ledger
  • Receipts
  • Reward Issuances
  • Save Data
  • Metadata
  • Metadata (3.4+)
  • Queries
  • Application CDN Git Deployment
  • Large Object API
  • Firebase Push Notifications
  • Email Templates
  • Event Reference
  • Element Static Content and Dashboard UI Plugins
  • User Authentication / Sign In
    • What is a User?
    • Email Verification
    • User Authentication in Elements
    • Account Linking
    • Setting Up Twitch OIDC Login (Backend)
    • OIDC Login for Thick Clients (Browser Redirect Flow)
    • Auth Schemes
      • Auth Schemes
      • OAuth2
      • OIDC
  • Features
    • Web3
      • Wallets
      • Vaults
      • Omni Chain Support
      • Smart Contracts
        • Smart Contracts
  • Queries
    • Advanced Operators
    • Object Graph Navigation
    • Boolean Queries
    • Base Query Syntax
  • Advanced Operators
    • .name
    • .ref

Your Game Code - Adding Custom Elements

  • Custom Code Overview
  • Windows Setup
  • Mac OS Setup
  • Ubuntu Linux Setup
  • Element Anatomy: A Technical Deep Dive
  • Introduction to Guice and Jakarta in Elements
  • Structuring your Element
  • Events
  • Packaging an Element with Maven
  • Deploying an Element
  • Preparing for code generation
  • Properties
  • Websockets
  • RESTful APIs
  • Direct MongoDB Access (3.5+)
  • Building the Example Element: A Complete Walkthrough
  • Building the Kotlin Example Element: A Complete Walkthrough

Configuration

  • Configuring External URLs for Deployment
  • Matchmaking – Comprehensive Guide
  • Direct Database Access and Batch Configuration
  • Connecting Namazu Elements to a TLS-Enabled MongoDB Replica Set
  • Batch Samples
    • Mission Upload Bash Script Sample
    • Item Upload Bash Script Sample

RESTful APIs

  • Importing into Postman
  • RESTful APIs Library
  • Swagger and Swagger UI

Add-Ons

  • Crossplay
    • Crossfire Client Libraries (JVM & Browser)
    • Crossfire Protocol Reference
    • Crossfire: Custom Matchmaking Algorithms
    • Namazu Crossfire (Multiplayer)
    • Deploying Namazu Crossfire in your game
  • Roblox
    • Roblox Overview
    • Secure Player Authentication & Registration
    • Global Matchmaking
    • Roblox Security Best Practices
  • Container on Demand
    • Namazu Conductor
    • Namazu Conductor Admin API
    • Configuring Namazu Conductor Providers
    • Streaming Job Stdio in Namazu Conductor
  • Commerce
    • Stripe
      • Stripe
      • Configuring the Stripe Element
      • Stripe REST API Reference
      • Stripe REST API Reference
      • Stripe Webhooks and the Typed Event Bus

Game Engine & Client Support

  • Unity
    • Elements Unity Plugin
    • Unity Crossfire Plugin
  • Gamemaker
    • Incorporating GMEXT-Elements into a GameMaker Project

Troubleshooting

  • Common Issues with Docker
  • Local SDK
    • Unable to deploy application : dev.getelements.elements.sdk.exception.SdkElementNotFoundException
    • Could not load class : java.lang.NoClassDefFoundError
  • Namazu Elements Community Edition
    • Common Issues with Docker
    • Unable to deploy application : dev.getelements.elements.sdk.exception.SdkElementNotFoundException
    • Running in the IDE
      • Exception in monitor thread while connecting to server localhost:27017
      • Could not deployAvailableApplications Jetty server Failed to bind to /0.0.0.0:8080 Address already in use

Releases

  • Release Process (3.9+)
  • 3.8 Release Notes
  • 3.9 Release Notes
  • 3.7 Release Notes
  • 3.6 Release Notes
  • 3.5 Release Notes
  • 3.4 Release Notes
  • 3.3 Release Notes
  • 3.2 Release Notes
  • 3.1 Release Notes

Namazu Agent

  • Namazu Agent Overview
  • Common Agent Tasks
  • Tips for Using the Namazu Agent

Namazu Cloud

  • Namazu Cloud Overview
  • Namazu Cloud Organizations
  • Namazu Cloud Subdomains
  • Namazu Cloud Instances
  • Namazu Cloud Products and SKUs
  • Namazu Cloud Add-ons
  • Namazu Cloud Account
  • Namazu Cloud Backups
  • Namazu Cloud Billing
View Categories
  • Home
  • Docs
  • Add-Ons
  • Commerce
  • Stripe
  • Stripe Webhooks and the Typed Event Bus

Stripe Webhooks and the Typed Event Bus

Est. read time: 3 min read

AI Doc Summarizer Doc Summary
AI Doc Summarizer Thinking Thinking

The Stripe Element keeps your platform’s view of payments, invoices, and subscriptions in sync with Stripe by receiving webhooks at a single endpoint, verifying their signature, and republishing them as internal Elements events. Every verified webhook is published as a raw event; the most common event types are also published as strongly-typed records so consuming code never has to deserialize a Stripe payload itself.


The Webhook Endpoint #

POST /stripe/webhook takes the raw request body and a Stripe-Signature header, and verifies them with the Stripe SDK’s Webhook.constructEvent against the configured webhook secret. This endpoint requires no Session authentication — Stripe can’t supply a Session secret — but every request is rejected unless its signature checks out:

  • 503 if no webhook secret is configured yet
  • 400 if the signature doesn’t verify
  • 200 {"received":true} once the event is published, or {"received":true,"typed":false} if the raw event was published but Stripe’s payload couldn’t be deserialized into a typed record (see below)

On every successfully verified webhook — regardless of type — the endpoint first publishes a StripeRawEvent and writes an entry to the event log, then attempts to dispatch a typed event. This ordering means a mismatch between this Element’s Stripe SDK version and the shape of an incoming event (an EventDataObjectDeserializationException) never loses the event — the raw event and audit log entry are already recorded before the typed dispatch is attempted.


Stripe Dashboard Setup #

In the Stripe Dashboard, go to Developers → Webhooks → Add endpoint.

  1. Use the “Account” webhook type, not “Event destinations / v2” — the v2 format uses thin payloads and a different signing scheme that this Element does not support.
  2. Set the endpoint URL to your deployed base URL plus the webhook path, e.g. https://your-host/Element/stripe/api/stripe/webhook.
  3. Subscribe to the event types you need. Any webhook that arrives with a valid signature is always forwarded as a RAW_WEBHOOK event regardless of which types you subscribe to; the typed events below only fire for their corresponding subscribed types.
  4. After saving, Stripe shows a Signing secret (whsec_...). Copy it into the dev.getelements.elements.stripe.webhook.secret attribute — see Configuring the Stripe Element.

Testing Webhooks Locally #

Forward Stripe events to a local instance with the Stripe CLI:

stripe listen --forward-to localhost:8080/Element/stripe/api/stripe/webhook

Typed Events #

Constants live on StripeEvents in the api module. Each is declared at the class level of the webhook endpoint with @ElementEventProducer, and each carries strongly-typed fields pulled straight off the corresponding Stripe object — no payload parsing required in the consumer.

StripeEvents constantStripe event typeRecordFields
PAYMENT_SUCCEEDEDpayment_intent.succeededStripePaymentSucceededEventpaymentIntentId, amount, currency, customerId
PAYMENT_FAILEDpayment_intent.payment_failedStripePaymentFailedEventpaymentIntentId, failureMessage, customerId
PAYMENT_CANCELEDpayment_intent.canceledStripePaymentCanceledEventpaymentIntentId, customerId
INVOICE_PAYMENT_SUCCEEDEDinvoice.payment_succeededStripeInvoicePaymentSucceededEventinvoiceId, paymentIntentId, amountPaid, currency
INVOICE_PAYMENT_FAILEDinvoice.payment_failedStripeInvoicePaymentFailedEventinvoiceId, subscriptionId, customerId, failureMessage
SUBSCRIPTION_CREATEDcustomer.subscription.createdStripeSubscriptionCreatedEventsubscriptionId, customerId, status, orgId
SUBSCRIPTION_UPDATEDcustomer.subscription.updatedStripeSubscriptionUpdatedEventsubscriptionId, customerId, status, orgId
SUBSCRIPTION_CANCELLEDcustomer.subscription.deletedStripeSubscriptionCancelledEventsubscriptionId, customerId, orgId
SUBSCRIPTION_TRIAL_WILL_ENDcustomer.subscription.trial_will_endStripeSubscriptionTrialWillEndEventsubscriptionId, customerId, trialEnd (ISO-8601), orgId
SETUP_INTENT_SUCCEEDEDsetup_intent.succeededStripeSetupIntentSucceededEventsetupIntentId, customerId
PAYMENT_METHOD_ATTACHEDpayment_method.attachedStripePaymentMethodAttachedEventpaymentMethodId, customerId
CHECKOUT_SESSION_COMPLETEDcheckout.Session.completedStripeCheckoutSessionCompletedEventsessionId, customerId, paymentIntentId, subscriptionId, mode, Metadata
RAW_WEBHOOKstripe.webhookStripeRawEventtype, eventId, rawJson — published for every verified webhook, including all of the above

The orgId field on subscription events is read from the Stripe object’s Metadata under StripeService.METADATA_ORG_ID — it’s only populated if the subscription (or its customer) was created with that Metadata key set, e.g. via createCustomer‘s orgId parameter or a Checkout Session’s Metadata.

Two of these event types also trigger a side effect inside the webhook handler itself: on PAYMENT_SUCCEEDED and INVOICE_PAYMENT_SUCCEEDED, the handler calls StripeService.recordPaymentReceipt to record a receipt in the platform receipt store, using the payment’s userId Metadata (silently skipped if that Metadata is absent or blank).


Consuming Events from Another Element #

Any Element that depends on Stripe’s api module can subscribe to these events with @ElementEventConsumer, annotating a method on any Guice-managed Service:

import com.google.inject.Inject;
import dev.getelements.elements.sdk.annotation.ElementEventConsumer;
import dev.getelements.elements.stripe.StripeEvents;

public class EntitlementService {

    @Inject
    private UserInventoryDao userInventoryDao;

    @ElementEventConsumer(StripeEvents.PAYMENT_SUCCEEDED)
    public void onPaymentSucceeded() {
        // called whenever a payment_intent.succeeded webhook is received
    }

    @ElementEventConsumer(StripeEvents.SUBSCRIPTION_CANCELLED)
    public void onSubscriptionCancelled() {
        // revoke access, notify player, etc.
    }

    @ElementEventConsumer(StripeEvents.RAW_WEBHOOK)
    public void onAnyWebhook() {
        // called for every verified Stripe webhook — use for event types
        // that don't have a dedicated typed event
    }
}

The Webhook Event Log #

Every verified webhook — typed or not — is also recorded to a MongoDB-backed audit log (StripeEventLogService, collection stripe_event_log) storing the Stripe event id, event type, and receipt timestamp. Browse it via the Stripe tab in the superuser admin panel, or query it directly with GET /stripe/events?type=&limit=20&offset=0, which supports filtering by event type and offset-based pagination. This is the fastest way to confirm whether a webhook actually arrived and how it was typed, without digging through Application logs.


Related Pages #

  • Stripe — Element overview and core concepts
  • Configuring the Stripe Element — setting the webhook secret and other attributes
  • Stripe REST API Reference — the webhook endpoint alongside every other REST endpoint
What are your Feelings
Still stuck? How can we help?

How can we help?

Updated on September 23, 2026
Stripe REST API ReferenceStripe
Table of Contents
  • The Webhook Endpoint
  • Stripe Dashboard Setup
  • Testing Webhooks Locally
  • Typed Events
  • Consuming Events from Another Element
  • The Webhook Event Log
  • Related Pages
  • Documentation
  • Terms of Service
  • Privacy Policy
  • Contact us
  • Linkedin
  • Join our Discord

Namazu Studios LLC is powered by Namazu Elements, an open source modular backend framework for connected games.

Namazu Elements
  • Download
  • About Elements
  • Open source
  • Documentation
  • Support
Namazu Studios
  • Case Studies
  • About Us
  • News
Best realtime game backends 2026
Get in Touch
  • info@namazustudios.com
  • Book a call
  • (619) 862-2890
  • Linkedin
  • Discord

©2008-2026 Namazu Studios. All Rights Reserved.