Stripe webhook setup - Step-by-step

All of that is very simple, and none of it requires anything to do with webhooks if you’re simply getting the subscription data from Stripe via an API call and displaying it on the page as and when you need it

Thanks Adam, that all makes sense although for me it’s far from simple! I wonder, if I rely on API’s (without webhooks) how will my Bubble app know if a user has unsubscribed? In other words, surely I will need to ‘send’ the API call to get that info from Stripe, but when do I send it?

Surely your customers are paying for more than just a message saying “You are subscribed”?

Yes, I didn’t want to overload you with the full details of my app, but essentially I have two tiers (see below).

Free users can create and send invoices to their customer but are limited to sending 3 invoices per month. Paid (subscribed) users can create and send unlimited invoices and they have access to a few other features.

So, when a user unsubscribed (downgrades from a paid plan to a free plan) I will then need to limit the amount of invoices they can send. This is probably easy, but first I need to make sure the user sees in their dashboard (in my app) clear text which says “You have unsubscribed but you can still enjoy using the app until xx.xx.xxxx”.

Bubble’s Stripe plugin makes use of Stripes Event subscription.updated which tells my app that the user has unsubscribed, but this information only comes when the subscription period has ended. So, the notice I am able to display to my customer when they unsubscribe is:

You are on a paid plan. your next payment is on xx/xx/xx

Of course, my user should see;

You have unsubscribed but you can still enjoy using the app until xx.xx.xxxx

I have found this issue impossible to fix. Stripe customer support even admitted to me that they need to add a new Event and Bubble support are also unable to help.

They key is just the name/identifier of the parameter (it can literally be anything you want to call it).

It is not editable so I can’t rename it. The Key is generated from the URL so maybe my platform has a bug.

To be clear, the URL I have used is https://api.stripe.com/v1/subscriptions/[sub_1L2X8DJjP8NRYZahVZ***] and the subscription part at the endsub_1L2X8DJjP8NRYZahVZ*** I took from a random users subscription. There is no ‘parent’ subscription ID so I just grabbed one of the subscribed users subscription ID’s.

If I create a new account in my app and go to ‘my subscriptions’ the user should initially see “You are on a free account” because they have not yet upgraded, but when using the above API settings I always see “You are on a paid account”.

I think I will reinstall the Stripe Plugin and follow the [this video] which worked previously for me, at least then my app can update the Status. Then, one again I will try and find a solution which allows me to display the following Text when a user unsubscribes “Your plan will be cancelled, but is still available until the end of your billing period on xx.xx.xxxx”.

You make the API call whenever you need the data - i.e. on page load, or when a specific action is taken on the page to display the data (such as in a popup). But if you’re using the API call as a data call (which you are) you don’t need to worry about that - the call will be made automatically when the element that uses the call as its datasource is loaded on the page.

Yes, I didn’t want to overload you with the full details of my app, but essentially I have two tiers (see below).

I assumed that was the case (and I assumed there was more to your app) - in which case there’s no way to avoid using webhooks to achieve what you’re trying to do (actually, I suppose you could instead make regular recurring API calls on the backend, but that wouldn’t be very efficient, especially when Stripe provides webhooks which makes that unnecessary).

I have found this issue impossible to fix.

I’m still not sure I understand the challenge you’re facing regarding ‘unsubscribed’ or cancelled subscriptions.

I’m able to manage this very easily in my apps (I currently have 2 live apps using Stripe subscriptions, and have never had any issues managing cancelled subscriptions). The Stripe customer.subscription.updated event tells you everything you need to know about the current status of a customer’s subscription - so by comparing that to the previous status (either in your own database, or using the Stripe event 'Previous Attributes;) it’s easy to see what has changed, so you can run the appropriate workflows in your app.

In terms of identifying a ‘cancelled subscription’ it’s as simple as checking the ‘Cancel At Period End’ - if it’s True (and wasn’t previously) then you know that the subscription has now been cancelled - so run the appropriate workflows.

Obviously, you’ll also need to manage the possibility that a customer cancels their subscription, and then ‘resumes’ it (aborts the cancellation) before the end of their billing period - so you’ll need a workflow to handle that as well.

It is not editable so I can’t rename it.

You define the Key in the URL (inside the square brackets) - it doesn’t make sense to use a subscription ID as the Key…

This makes sense, thank you for explaining.

In terms of identifying a ‘cancelled subscription’ it’s as simple as checking the ‘Cancel At Period End’ - if it’s True (and wasn’t previously) then you know that the subscription has now been cancelled - so run the appropriate workflows.

I’m going to set up the Bubble’s Stripe Plugin again and then see if I can find why I struggled to do what you’ve suggested above. There must have been something I was missing if you say it’s that easy.

Obviously, you’ll also need to manage the possibility that a customer cancels their subscription, and then ‘resumes’ it (aborts the cancellation) before the end of their billing period - so you’ll need a workflow to handle that as well.

Good point. Thank you for pointing that out.

You define the Key in the URL (inside the square brackets) - it doesn’t make sense to use a subscription ID as the Key…

The Key is automatically generated from the URL so I have no control over it. In any case I will leave the API route and use the webhooks inbuilt in Bubble’s Stripe Plugin.

Of course you have control over it - you literally just type it…

In any case I will leave the API route and use the webhooks inbuilt in Bubble’s Stripe Plugin.

The Stripe plugin is just pre-defined API calls - there are no webhooks involved with the plugin (as far as I know, although I can’t imagine how there could be, as the plugin doesn’t have access to your Stripe account to create any webhooks)…

This is odd because it won’t let me, when I click inside the field I can not type, I can’t even delete it. I just tried again now.

The Stripe plugin is just pre-defined API calls

Ok I didn’t know this.

In terms of identifying a ‘cancelled subscription’ it’s as simple as checking the ‘Cancel At Period End’ - if it’s True (and wasn’t previously) then you know that the subscription has now been cancelled - so run the appropriate workflows.

I’ve now set up Bubble’s Stripe Plugin again and users can subscribe and unsubscribe successfully, a good start!

I don’t see ‘Cancel At Period End’ from my dropdown options (see below). Do I need to create a subscription.updated webhook to have access to this option? The video tutorial said to use subscription.canceled which I have but I don’t know how to access the ‘Cancel At Period End’ feature.

cc

The setup is simple, I have added fields to the User datatype;

2

The workflow when a user pays is like this;

…and I am requesting webhook data from Stripe subscription.canceled by having a backend workflow like this;

I suspect you’re trying to type in the Key box… (as I said before, you define the Key in the actual URL - inside the square brackets)

image

I don’t see ‘Cancel At Period End’ from my dropdown options (see below).

No, you can’t access that from the Stripe plugin - you’ll need to make your own API call, or use a webhook to access the Subscription Object data.

Do I need to create a subscription.updated webhook to have access to this option?

You need to access the subscription object. How you get that is up to you (from an API call or a webhook), but if you want to run a workflow when it happens, then obviously that has to be done via a webhook.

The video tutorial said to use subscription.canceled

There’s no such event in Stripe, so I’m not sure what that’s referring to?

…and I am requesting webhook data from Stripe subscription.canceled by having a backend workflow like this;

Again, Stripe doesn’t have a subscription.canceled event, so I’m not sure what you mean there?..

I suspect you’re trying to type in the Key box… (as I said before, you define the Key in the actual URL - inside the square brackets)

Yes, I was trying to type in the Key box, thank you for the screenshot. Sorry that I missed your previous comment saying I define the Key in the actual URL. I am missing things because I’ve been trying so many things and perhaps I am rushing or stressed.

I hope you can get me ‘over the line’ on this one because it’s been more than a month of trying everyday! Who would have thought to simply know when a user cancels a subscription (not when the subscription ends but when the user first clicks the unsubscribe button) could be so hard!

No, you can’t access that [‘Cancel At Period End’] from the Stripe plugin - you’ll need to make your own API call, or use a webhook to access the Subscription Object data.

Ok thank you for letting me know, I will try and implement a webhook.

There’s no such event in Stripe, so I’m not sure what that’s referring to?

I apologies, it is actually customer.subscription.deleted, I see why I got that wrong, the video tutorial misnamed in in their backend workflow - again, I need to slow down and triple check before replying to you as I am rushing. This event occurs whenever a customer’s subscription ends so, as you’ve said, I need to access Subscription Object data if I want to make use of ‘Cancel At Period End’.

You need to access the subscription object. How you get that is up to you (from an API call or a webhook), but if you want to run a workflow when it happens, then obviously that has to be done via a webhook.

I’m not sure which Event I need to use, Stripe API reference doesn’t mention a customer unsubscribing from a plan and neither does the simplified Webhook Event Cheatsheet.

UPDATE: Good news, I went back over my emails from Stripe and I had already asked them which Event would tell me when a user clicks unsubscribe, they said;

when canceling a subscription at the end of the billing period, only a customer.subscription.updatedevent will fire up as customer.subscription.deleted will only occur once the subscription ended. So I agree that it will be more logical to name it as “customer.subscription.ended” or add this as another webhook event.

Ok, I will try and set up a customer.subscription.updatedwebhook now!

I will try and follow your instruction below;

In terms of identifying a ‘cancelled subscription’ it’s as simple as checking the ‘Cancel At Period End’ - if it’s True (and wasn’t previously) then you know that the subscription has now been cancelled - so run the appropriate workflows.

So the best way to do it (this is how we do it in our Subscription apps)… is to set up a Webhook in Stripe with the customer.subscription.updated event and point it to your endpoint (API Workflow) in Bubble.

Then, in that API workflow, use a conditional action to trigger another workflow, based on the request data’s object (specifically: when request data's object cancel_at_period_end is 'yes' AND request data's object status is 'active' (you’ll probably also want to compare it to something in your own database to prevent the same workflow from running again if the user makes some additional change to their subscription, such as comparing your own database’s subscription status, or cancel fields)

Then use the second workflow to make the necessary changes to your User in your database.

I created a new [Text] field in the User Datatype called ‘Just_Unsubscribed’ . I then update this field with “Yes” when the backend workflow runs.

The first backend API first accepts the payload from Stripe…

and then Only when conditions are met do I move to the next API which updated the database. Although, I found a potential issue - the payload sends “cancel_at_period_end”: true but I am only able to select “Yes” from the conditions dropdown options.

tr

I am planning on dispolay the correct text using these conditions;

1

I have tested this and it doesn’t work. When I cancel my subscription I return to my website, for some reason I am always logged out when returning, the return URL is https://mydomain.com/?selected=subscription

The text should display ‘You JUST cancelled’ but it says ‘You are on the £8.99 plan’.

I think I found the issue, I can’t update the User because I get red text?

Perhaps, in order to be able to search for Request Data's objects customer I will need to create a new webhook for this API (user_clicked_unsubscribe). The trouble is, as soon as I switch to Detect request Data I see a new field highlighted in red on the previous API and it all get’s more confusing again.

I honestly don’t mean this to sound patronizing… but I genuinely don’t understand what’s hard about this…

When a Customer cancels their subscription (or makes ANY other changes to their subscription), Stripes tells you via a webhook containing the customer.subscription.updated event. That’s all you need.

I’m not sure which Event I need to use, Stripe API reference doesn’t mention a customer unsubscribing from a plan and neither does the simplified Webhook Event Cheatsheet.

At this point I need to get some clarification - due to the terminology you’re using - just to make sure we’re both talking about the same things…

Are you talking about Subscriptions or Plans? (those are two different things in Stripe) - you mention “Unsubscribing from a Plan” - so now I’m not sure if I’ve misunderstood this whole thread…

I’ve assumed you’re talking about ‘Subscriptions’ here…

Also, I’ve scoured the Stripe API docs (and main docs), and ‘Unsubscribe’ is not a term they use at all - there’s no such thing as “Unsubscribing” (from a plan, a subscription, or anything else as far as I can tell) in Stripe.

So again, just to clarify, I’m assuming what you’re actually talking about is a customer Cancelling a Subscription?

In which case the docs are pretty clear (at least they were clear to me when I first read them),

It says it right here:

Although, I found a potential issue - the payload sends “cancel_at_period_end”: true but I am only able to select “Yes” from the conditions dropdown options.

It’s a Boolean field (true/false) - Bubble speak for that is Yes/No (it’s the same thing).

I can’t really comment much on the rest of your post, as I don’t really understand what you’re doing…

But just a couple of points that might help:

1

Those are two separate, and non-exclusive conditions, both changing the same thing (the text). Conditions are always applied in the order they appear in the properties editor, so in this case, regardless of whether the first condition is true or not, the last one will always be the one that gets applied if both are true (i.e. the text will always say “You are on the £8.99 plan” if the xSubscription_status is Active)

Surely that should just be Request Data’s Object Customer?

Perhaps, in order to be able to search for Request Data's objects customer I will need to create a new webhook for this API (user_clicked_unsubscribe). The trouble is, as soon as I switch to Detect request Data I see a new field highlighted in red on the previous API and it all get’s more confusing again.

I don’t understand what you mean there - but you can’t schedule a public API workflow from within another backend workflow (as far as I know).

When a Customer cancels their subscription (or makes ANY other changes to their subscription), Stripes tells you via a webhook containing the customer.subscription.updated event. That’s all you need.

True, although you also need the knowledge of how to use that data, how to set up API’s and/or webhooks and how to then display the text in your website!

Are you talking about Subscriptions or Plans?

Sorry, I am talking about a subscription. I have always used both interchangeably, for example my gym has three subscription plans; basic plan, middle plan and top plan… they are all monthly subscriptions and all ‘plans’. I will only use the word subscription if that is how Stripe does it.

In which case the docs are pretty clear (at least they were clear to me when I first read them),

Thanks for highlighting in red, I guess the terminology is unfamiliar for me, language like subscription ‘object’ is not intuitive, I’d have named it subscription ‘data’ if I created Stripe!

Also, subscription ‘canceled’ is not what people do in the real world, they ‘unsubscribe’ so I was searching for those keywords. To me, cancelling something is to go back on your original purchase.

Anyway, that is simply me not understanding common terminology in the Stripe environment I guess, maybe some general terminology is different in the UK. But, thank you for correcting me.

I see that when cancel_at_period_end is True AND the user is still subscribed will give me the information I need ie; when those two conditions are true I know that the user just clicked unsubscribe.

Trouble, is I don’t know how to set this up on my site.

Surely that should just be Request Data’s Object Customer?

Yes it should be but it won’t allow me to choose that.

I appreciate your efforts to help me but I think for some things the forum is not an ideal way to explain complex things. I never want to waste your time because you give so much of it away for free and as always I deeply appreciate it. I think for this particular task I need to pay someone because I have gone round and round always getting to this stage, the webhook never works.

  • just updated my comment.

Yes, of course… APIs are intended for use by developers, not laypeolpe - so if you’re not a developer (which I’m certainly not) then the onus is on you to at least learn the basics.

Thanks for highlighting in red, I guess the terminology is unfamiliar for me, language like subscription ‘object’ is not intuitive, I’d have named it subscription ‘data’ if I created Stripe!

‘Object’ means something specific in programming, and in JSON even more specifically - ‘data’ is a very generic term, that could mean anything. Again, Stripe’s API has been created by developers for use by developers, so standard programming terminology is used.

Also, subscription ‘canceled’ is not what people do in the real world, they ‘unsubscribe’ so I was searching for those keywords. To me, cancelling something is to go back on your original purchase.

That just goes to show how using standard terminology is very important - to me (and I’d guess anyone else who’s involved in online marketing), ‘unsubscribing’ is something you do from an email list - it doesn’t make sense (to me) to use the term ‘unsubscribe’ when referring to payments - it’s too easily confused, and quite ambiguous. ‘Cancelling’ is a much more clear and logical term to me (and presumably to Stripe, and those who use it) - important when you’re dealing with people’s money.

But in any case, that’s irrelevant - all the terminology is explained in the Stripe docs - if you’re planning to work with Stripe’s API (or any API for that matter) it’s really important spending some time familiarising yourself with the API docs and objects etc. - at least for the objects you’ll be dealing with.

I take your point and I admit you are correct. I am not a coder which is what attracted me to Bubble but I guess for this task I am dealing with Stripe which, as you say, adheres to stricter terminology.

UPDATE: It worked! Finally I have a notice on my website when the user clicks ‘cancel plan’.

Here is the solution;

5

Ok, you originally said this;

in the API workflow I should use a conditional action to trigger another workflow, based on the request data’s object (specifically: when request data’s object cancel_at_period_end is ‘yes’ AND request data’s object status is ‘active’.

This didn’t work (for me) but when I did it the simple way with just one API it worked (see image above). I know there would have been a good reason you suggested to trigger another workflow but I can’t recall what that was?

Damn … if a user renews their subscription the notice on my website does not update, it remains on 'You JUST Cancelled".

Fail :weary:

Those are two separate, and non-exclusive conditions, both changing the same thing (the text).

I understand, thanks.

1 Like

I’ve finally fixed this, I’m not sure if I’ve complicated it but it works! I am now able to show the following info;

  1. When a subscription is created I can say “You are on the Pro plan. Your next payment of £8.99 will be taken on xx.xx.xxxx”.

  2. When a subscription is cancelled and due to expire I can say “Your plan will be cancelled, but is still available until the end of your billing period on xx.xx.xxxx”.

  3. When a user renews their subscription immediately after un-subscribing I can say “You just re-subscribed to the Pro plan. Your next payment of £8.99 will be taken on xx.xx.xxxx”.

Stripe Events

The default Stripe ‘Status’ event tells me if a user is currently on a paid plan. But, if they cancel a plan their Status will remain ‘active’ until then end of the current period. So, I needed to know the instant a user cancels their plan, this is done by listening to the Event cancel_at_period_endand updating my database.

I created a field in my database called ‘just_cancelled’ which is either ‘yes’ or ‘no’, depending on if cancel_at_period_end is yes or no.

To be clear, the instant a user cancels their plan, their ‘just_cancelled’ field in my DB becomes ‘yes’. And, the instant a user subscribes their ‘just_cancelled’ field in my DB becomes ‘no’.

Backend

The backend has two steps when for the Event “subscription_updated”. The first updates my ‘just_cancelled’ field with a ‘yes’ when the cancel_at_period_end is ‘yes’. This means the user has just cancelled their subscription and they are still ‘active’ until the end of the current period.

The other step marks the same field with a ‘no’ when thecancel_at_period_end is 'no. This means the user has an active subscription.

1. When a subscription is created

When cancel_at_period_endis empty AND their status is ‘active’ I know that they have literally just clicked subscribe for the first time.

1

2. When a subscription is cancelled and due to expire

When cancel_at_period_endis ‘yes’ AND their status is ‘active’ I know their subscription is cancelled and due to expire. Again, thanks to @adamhholmes for this tip.

2

3. When a user renews their subscription immediately after unsubscribing

I know that when an ‘active’ user cancels their subscription, my DB shows;
Status = Active
Just_cancelled = Yes

So, when the same user renews their subscription immediately, my DB shows;
Status = Active
Just_cancelled = No

So I can perform the following search to find when a user re-subscribes immediately after unsubscribing;

3

1 Like