Stripe Webhook: Empty IDs & matching issues for returning customers in Backend Workflow

I am trying to automate user subscription tracking in Bubble by parsing Stripe checkout.session.completed webhooks. The goal is to update the User record with stripe_customer_id, stripe_subscription_id, and set is_premium = true..

Current Setup & What Works:

  • Endpoint receives checkout.session.completed webhooks with 200 OK.

  • Search for Users successfully matches the user by email using direct field selection on Request Data.

  • is_premium consistently updates to true.

  • Initial Test Behavior: On first setup, live events left the ID fields blank, but manually clicking Resend in Stripe successfully populated stripe_customer_id and stripe_subscription_id.

The Issue:

  • On live checkouts, stripe_customer_id and stripe_subscription_id evaluate to (empty) on the User record.

  • Server logs show the payload contains the IDs, but for returning customers (who already exist in Stripe and have an old stripe_customer_id in Bubble), it occasionally pulls a previous subscription ID or leaves the field blank.

  • Rebuilt the workflow with a 10-second delay step to rule out database/timing race conditions, but the issue persists.

What is the standard, best-practice Bubble logic to handle checkout.session.completed for both new users (matched by email) and returning customers (matched by existing stripe_customer_id / email) to ensure the current subscription_id always saves reliably?

Don’t match on email. Pass your user’s ID as client_reference_id when you create the checkout session, then look the user up by that in the webhook and save the customer and subscription IDs from there.

Resend works because it’s one event. A real checkout fires several (subscription created, invoice paid…) in random order, so if your endpoint listens to more than checkout.session.completed, a later one can overwrite your IDs with blanks. A delay won’t fix it. Check which events your endpoint is subscribed to in Stripe.