Examples
Five Stripe webhook receiver examples: payment success provisioning, failure retry and notify, refund order status update, dispute response, and wildcard charge filter.
Example 1: Payment Success — Provision Service
Node settings:
WebhookSecret: whsec_your_signing_secret_here
AllowedEventTypes: payment_intent.succeeded,charge.succeeded
RequireKnownCustomer: true
EnableIdempotencyCheck: true
Output fields used downstream:
{{ nodes.stripeTrigger.output.event_type }} // "payment_intent.succeeded"
{{ nodes.stripeTrigger.output.customer_id }} // "cus_PqRsTuVwXy"
{{ nodes.stripeTrigger.output.payment_intent_id }} // "pi_3NxK..."
{{ nodes.stripeTrigger.output.amount }} // 4900 (cents)
{{ nodes.stripeTrigger.output.currency }} // "usd"
{{ nodes.stripeTrigger.output.metadata }} // { "order_id": "ORD-421", "plan": "pro" }
{{ nodes.stripeTrigger.output.receipt_email }} // "customer@example.com"
{{ nodes.stripeTrigger.output.livemode }} // true
Workflow steps after trigger:
- IfCondition — verify
livemode == truebefore provisioning to avoid test events touching production systems - MongoDB (findOne) — look up the customer record using
customer_idand theorder_idfrom metadata - MongoDB (update) — update order status to
paidand storepayment_intent_id - HTTP Request (provisioning API) — activate the customer's account or deliver the purchased service
- Email (SMTP) — send a payment confirmation receipt to
receipt_emailwith the amount (divide by 100) and order reference from metadata - Slack — notify
#paymentschannel of the successful transaction
Expected outcome: Service is provisioned within seconds of payment confirmation. Customer receives a receipt email. The payment record is updated in the database.
EnableIdempotencyCheck prevents double-provisioning if Stripe retries the delivery.Example 2: Payment Failure — Retry and Notify
Node settings:
WebhookSecret: whsec_your_signing_secret_here
AllowedEventTypes: payment_intent.payment_failed
Output fields used downstream:
{{ nodes.stripeTrigger.output.customer_id }} // for DB lookup
{{ nodes.stripeTrigger.output.last_payment_error_code }} // "card_declined", "insufficient_funds"
{{ nodes.stripeTrigger.output.last_payment_error_message }} // human-readable reason
{{ nodes.stripeTrigger.output.amount }} // attempted amount
{{ nodes.stripeTrigger.output.currency }}
{{ nodes.stripeTrigger.output.metadata }} // order/subscription reference
Workflow steps after trigger:
- MongoDB (findOne) — look up the customer record and email address using
customer_id - Switch — branch on
last_payment_error_code:card_declinedorinsufficient_funds— send "your payment was declined" email with a payment update linkexpired_card— send "your card has expired" email with a card update linkdo_not_honor— escalate to billing team in Slack for manual review
- MongoDB (update) — increment
failed_payment_counton the customer record - IfCondition — if
failed_payment_count >= 3, flag the account for review and notify the billing team - Delay — wait 3 days
- Email (SMTP) — send a follow-up reminder if payment has not been updated
Note: Stripe automatically retries failed subscription payments on its Smart Retries schedule. This workflow provides a customer communication layer on top of Stripe's automated retries — personalised messaging based on the specific decline reason reduces involuntary churn.
Example 3: Refund — Update Order Status
Node settings:
WebhookSecret: whsec_your_signing_secret_here
AllowedEventTypes: charge.refunded
EnableIdempotencyCheck: true
Output fields used downstream:
{{ nodes.stripeTrigger.output.charge_id }} // "ch_3NxK..."
{{ nodes.stripeTrigger.output.payment_intent_id }} // to look up the order
{{ nodes.stripeTrigger.output.amount_refunded }} // total refunded in cents
{{ nodes.stripeTrigger.output.amount }} // original charge amount
{{ nodes.stripeTrigger.output.refund_reason }} // "requested_by_customer"
{{ nodes.stripeTrigger.output.customer_id }}
{{ nodes.stripeTrigger.output.currency }}
Workflow steps after trigger:
- MongoDB (findOne) — find the order by
payment_intent_idfrom metadata - IfCondition — check if this is a full refund:
amount_refunded == amount - Full refund branch:
- MongoDB (update) — set order status to
refunded - HTTP Request (access API) — revoke service access for the customer
- MongoDB (update) — set order status to
- Partial refund branch:
- MongoDB (update) — add a refund record to the order's refund history, keep status as
partially_refunded
- MongoDB (update) — add a refund record to the order's refund history, keep status as
- Email (SMTP) — send refund confirmation: "Your refund of {{ amount_refunded / 100 | currency }} has been processed. Please allow 5–10 business days for it to appear on your statement."
Expected outcome: Order records are kept accurate for both full and partial refunds. Full refunds trigger immediate access revocation. Customers receive a clear confirmation with the exact refund amount and processing timeline.
Example 4: Dispute — Pause Account and Alert Team
Node settings:
WebhookSecret: whsec_your_signing_secret_here
AllowedEventTypes: charge.dispute.created,charge.dispute.closed
IncludeFullEventObject: true
Output fields used downstream:
{{ nodes.stripeTrigger.output.event_type }} // "charge.dispute.created" or "charge.dispute.closed"
{{ nodes.stripeTrigger.output.dispute_id }} // "dp_..."
{{ nodes.stripeTrigger.output.dispute_reason }} // "product_not_received", "fraudulent", etc.
{{ nodes.stripeTrigger.output.dispute_status }} // "needs_response"
{{ nodes.stripeTrigger.output.amount }} // disputed amount in cents
{{ nodes.stripeTrigger.output.currency }}
{{ nodes.stripeTrigger.output.customer_id }}
{{ nodes.stripeTrigger.output.evidence_due_by }} // Unix timestamp — evidence deadline
{{ nodes.stripeTrigger.output.charge_id }}
Workflow steps after trigger:
- Switch — branch on
event_type:charge.dispute.created— continue with the dispute response steps belowcharge.dispute.closed— branch ondispute_status: ifwon, restore account; iflost, write off the amount and update records
- MongoDB (findOne) — find customer by
customer_id - HTTP Request (account API) — set account status to
under_reviewto prevent further charges - MongoDB (update) — record the dispute with
dispute_id, reason, amount, and evidence deadline - DataMapping — convert
evidence_due_byUnix timestamp to a readable date - Slack — post to
#billing-disputes: "DISPUTE OPENED — Customer: {{ customer_id }} | Amount: {{ amount / 100 | currency }} | Reason: {{ dispute_reason }} | Evidence due: {{ evidence_due_date }} | Dispute ID: {{ dispute_id }}" - Email (SMTP) — send a case summary to the billing team with full dispute context and the Stripe Dashboard link
Evidence deadline: The
evidence_due_by timestamp is critical. Use a DataMapping node to convert it from Unix to a readable date and include it prominently in the Slack alert. Missing the evidence deadline means automatically losing the dispute regardless of its merits.Example 5: Wildcard Filter for All Charge Events
Node settings:
WebhookSecret: whsec_your_signing_secret_here
AllowedEventTypes: charge.*
AllowedCurrencies: usd,gbp
MinimumAmount: 100
EnableIdempotencyCheck: true
This catches all 5 charge events: charge.succeeded, charge.failed, charge.refunded, charge.dispute.created, charge.dispute.closed.
Switch node downstream — branch on event_type:
// Switch node condition expressions:
Case 1: {{ nodes.stripeTrigger.output.event_type }} == "charge.succeeded"
→ Provision service branch
Case 2: {{ nodes.stripeTrigger.output.event_type }} == "charge.failed"
→ Failure notification branch
Case 3: {{ nodes.stripeTrigger.output.event_type }} == "charge.refunded"
→ Refund processing branch
Case 4: {{ nodes.stripeTrigger.output.event_type }} == "charge.dispute.created"
→ Dispute response branch
Case 5: {{ nodes.stripeTrigger.output.event_type }} == "charge.dispute.closed"
→ Dispute closure branch
MinimumAmount filter: The
MinimumAmount: 100 setting (= $1.00 / £1.00) filters out test charges and micro-transactions below 1 currency unit. Adjust this value to match the minimum meaningful transaction amount for your business. AllowedCurrencies ensures only USD and GBP transactions trigger this workflow — EUR or other currency events are discarded.