In a Stripe webhook handler, branch first on event.type. That tells you what kind of event arrived and what resource event.data.object contains. If the event is checkout.session.completed, then inspect the Checkout Session—such as its mode and related object references—to choose the right application logic for a one-time purchase or a subscription.
Why the event type comes first
A webhook event is not a generic “payment happened” notification. Its type identifies the event, and its data.object is the resource associated with that event. For example, checkout.session.completed carries a Checkout Session, while payment_intent.succeeded carries a PaymentIntent. Read the object according to the event type before accessing resource-specific fields. See Stripe’s event types reference.
As an Amazon Associate I earn from qualifying purchases.
One customer action can also produce multiple events. Stripe gives subscription creation as an example that can trigger both customer.subscription.created and charge.succeeded. Treat each as a distinct signal with its own resource and purpose rather than assuming one event represents every relevant business change. Stripe’s webhooks guide explains event handling and delivery behavior.
For Checkout, inspect the Session after dispatch
Stripe Checkout supports one-time payments, subscriptions, and payment-method setup. When your handler receives checkout.session.completed, the object is a Checkout Session. Its mode and related references give your application the context to select the appropriate path; the specific fulfillment action is defined by your own product and entitlement rules.
#1 Best Overall
| Session mode | Stripe use | Related resource or next decision |
|---|---|---|
payment |
One-time payment | After successful payment, the Session can reference a successful PaymentIntent. Apply your one-time fulfillment rules. |
subscription |
Fixed-price subscription using Stripe Billing | After successful payment, the Session can reference an active Subscription. Apply your subscription and access rules. |
setup |
Save payment details for later charges | This is not one of the two purchase paths above; handle it according to your saved-payment-method flow. |
These mode definitions and Session relationships are documented in Stripe’s Checkout Session API reference. The product names in your own integration do not determine the event schema: use the Stripe event type and Session data to map an event to your application’s product logic.
Structure the handler as two decisions
- Verify the request. Validate the
Stripe-Signatureheader using the original raw request body and the endpoint’s signing secret before performing side effects. - Dispatch by event type. Route
checkout.session.completedto Checkout Session handling,payment_intent.succeededto PaymentIntent handling, and other supported types to their own handlers. - Interpret the event’s object. For a completed Checkout Session, inspect its mode and relevant references; do not treat every
data.objectas the same resource. - Apply product-specific rules. Decide which order, subscription, access grant, or other application action follows from the verified event and resource state.
- Record and acknowledge safely. Track processed event IDs, complete or queue the work, and return a successful response once the event has been safely accepted.
Stripe requires the raw request body for signature verification; middleware that parses or alters it can make verification fail. Use an official Stripe library and verify before fulfillment, access grants, or database changes. Stripe also describes IP allowlisting as an additional protection. See Stripe’s signature verification guide.
Rank #2
Do not infer business order from webhook arrival
Stripe does not guarantee that events arrive in the order they were generated. Its subscription example includes customer.subscription.created, invoice.created, invoice.paid, and possibly charge.created; a handler must not depend on a fixed sequence. Snapshot event creation times have second-level granularity, so different events can share a timestamp. Do not use timestamps to infer which event should be processed first.
Recommended Free Tools
Webhook endpoints can receive the same event more than once. Deduplicate deliveries using the event ID. Stripe also notes that separate Event objects can describe the same underlying change; in that case, use the combination of data.object ID and event.type when identifying duplicate business processing. If required information has not arrived, retrieve the related object from Stripe’s API rather than waiting for a particular delivery order. These behaviors and recommendations are covered in the webhooks guide.
Rank #3
Retries, resends, and event versions
Stripe’s Webhooks documentation, accessed in 2026, says automatic retries run for up to three days in live mode, while sandbox deliveries are retried three times over a few hours. Manual resends are also available: up to 15 days through the Dashboard and up to 30 days through the CLI after event creation. These are operational details that can change; check Stripe’s current delivery guidance when configuring monitoring and recovery.
Event structure is tied to the API version applicable when the event occurs. Updating the account API version does not retroactively change existing Event objects. Handle the version configured for your event destination, and do not assume stored event snapshots will be rewritten after an upgrade. Stripe documents event versioning in its webhooks guide.
Quick Recap
Best Value
Rank #4
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




