Stripe webhook setup - Step-by-step

It’s literally the first thing in the Stripe API docs (at the very top of the page):

Perfect. I have now made my ‘GET’ URL

https://api.stripe.com/v1/subscriptions/sub_`[my Stripe-Account ID]`

You don’t put your account ID there… you need to put the ID of the subscription you want to retrieve.

As for the rest… there’s a lot wrong here…

Firstly, I’m not sure you want to be including the private key the URL (it might work that way I’m not sure) - but I use Private key in Header as the Authentication type for Stripe.

In any case, you need to include the ‘live’ API key (your live Stripe Secret Key, NOT public key), preceded by the word Bearer, then a space, where it says ‘Key Value’, and your Development key (i.e. your test secret key) where it says Development Key Value. e.g. Bearer sk_live_******************** & Bearer sk_test_********************

The Key name needs to be Authorization

You don’t need any headers in you actual Get Subscription call, just set up the URL with a dynamic value for the Subscription ID (use to make it dynamic)

Also, it’s probably not a good idea to post your Stripe API keys here in the forum (certainly not your secret keys - even test ones), nor your Stripe account ID, for security reasons - so I’d delete those from your post if I were you.

1 Like

It’s literally the first thing in the Stripe API docs (at the very top of the page):

So it is! I wasn’t initially aware what a ‘base URL’ was, Stripe needs an ‘API for dummies’ page for the likes of me!

You don’t put your account ID there… you need to put the ID of the subscription you want to retrieve.

Thank you, I have now made my ‘GET’ URL https://api.stripe.com/v1/subscriptions/sub_prod_Lb1hTL2xxxxxxx. I used the product ID, not the price ID.

I use Private key in Header as the Authentication type for Stripe.

I’ve done the same and added my Live and Development keys using the instructions you provided and the Key name is Authorization.

You don’t need any headers in you actual Get Subscription call, just set up the URL with a dynamic value for the Subscription ID (use to make it dynamic)

Am slightly confused because you said the ‘GET’ URL should use the product ID like this: https://api.stripe.com/v1/subscriptions/sub_prod_Lb1hTL2xxxxxxx

Should it be like this?

https://api.stripe.com/v1/subscriptions/sub_[Subscription ID]

Initially I am trying to retrieve data when a user first signs up so that I can update my users Status in my app. Here’s what I have:

Also, it’s probably not a good idea to post your Stripe API keys here in the forum (certainly not your secret keys - even test ones), nor your Stripe account ID, for security reasons - so I’d delete those from your post if I were you.

Thank you, very kind of you to give me that heads up. I have deleted the images now.

No… you’re retrieving a Subscription (not a product), so you need to use the subscription ID.

Should it be like this?
https://api.stripe.com/v1/subscriptions/sub_[Subscription ID]

If you want to be able to define the subscription dynamically in your app then yes (although the subscription ID include the sub_ prefix, so don’t include it twice).

Thanks again, apologies for my slow replies, I have just had a second failed root canal on a tooth and have been in pain :weary:

No… you’re retrieving a Subscription (not a product), so you need to use the subscription ID.

As far as I can tell Stripe assigns the word ‘product’ even to subscriptions. See the screenshot below of my subscription, it only offers a product ID.

1

If you want to be able to define the subscription dynamically in your app then yes (although the subscription ID include the sub_ prefix, so don’t include it twice).

I’ve added [Subscription ID] but it’s not able to initialize the call due to incorrect URL. When I say that I’ve added [Subscription ID], I mean I have literally just added that, I am not replacing the text within the so this may be incorrect?

I am assuming that the empty value should be the actual subscription ID, ie. the ID in the image above. I have tried adding this to the empty value but no joy.

That’s incorrect. Every object has its own ID with its own prefix. prod_************* is only for products…

The Subscription object ID is sub_*****************

Check the stripe docs to read about the Subscription object that you’re trying to receive: Stripe API Reference - Subscriptions

See the screenshot below of my subscription, it only offers a product ID.

The image you’ve attached is for a Product (not a Subscription).

Subscriptions are found on the Subscriptions Tab of your Stripe Dashboard - click More, then Subscriptions to see them

I am assuming that the empty value should be the actual subscription ID,

Yes, indeed, in order to initialize the call you need to include a valid Subscription ID in the URL

ie. the ID in the image above.

No, that’s a Product ID - you need to include a valid Subscription ID (i.e. one that starts with sub_****************).

You can find one in the Subscriptions section of your Stripe Dashboard, assuming you have subscriptions in your test account (click on More, the Subscriptions). I’d have thought you’d also have some saved in your app database as you were saving them there before.

Note: you’ll also want to uncheck the ‘Private’ box next to the Subscription ID parameter if you want to be able to define the Subscription ID dynamically in your data calls (which presumably you do)

Thank you.

If Stripe does indeed have a separate Product and Subscription section then their UX is weird.

Products are found under a product tab (logical), yet Subscriptions are found under Billing tab. Stranger still, if I create a new subscription it is automatically moved the the Product section and behaves exactly as a Subscription would, ie; it bills the users monthly.

Subscriptions are found on the Subscriptions Tab of your Stripe Dashboard

I don’t have a Subscriptions Tab. I have located that page but the Subscriptions which I created are not there, what I do find is a list of users who joined my subscription.

I have followed the instructions on how to create a subscription. On the Billing page I click “Create subscription” and I am once again taken to the ‘Add a new product’ page. Notice the URL says I am in ‘subscriptions’ but the content is for Products.

As much as I have looked, I don’t see a Subscription ID anywhere for my previous or new subscriptions?

Note: you’ll also want to uncheck the ‘Private’ box next to the Subscription ID parameter

Thank you, I’ve done that now.

Yeah, it looks like you’ve got a different version of the Stripe dashboard to me (for some reason)…

In any case, you can find your Subscriptions in a few places actually (Billing, Payments, Subscriptions etc. it doesn’t mater how you get there…)

but the Subscriptions which I created are not there, what I do find is a list of users who joined my subscription.

No, those ARE the Subscriptions (it sounds to me as if you don’t quite understand what a Subscription is in Stripe - you seem to be confusing Products, Customers, and Subscriptions).

A Subscription is an actual Subscription, by a Customer, to a Product.

E.g. in you image above it shows that the Customer ‘User4@test.com’ has an Active Subscription to the Product ‘testSubscriptionDaily’. That’s what a Subscription is.

I have followed the instructions on how to create a subscription. On the Billing page I click “Create subscription” and I am once again taken to the ‘Add a new product’ page. Notice the URL says I am in ‘subscriptions’ but the content is for Products.

That IS the create Subscription Page - but it looks as though you’ve clicked on Add New Product? (that’s the only way I can replicate that behaviour)…

Did you click Add New Product? (if not, then it could be a bug with Stripe, although I’ve never experienced anything like that before…)

In any case you should just be able to close the Add New Product Window.

As much as I have looked, I don’t see a Subscription ID anywhere for my previous or new subscriptions?

When you click on a Subscription to open it the Subscription ID will be shown in the top right of the screen, or in the main Subscription Details Panel:

Thanks @adamhholmes , I see the Subscription ID now and I know why I was confused.

A Subscription is an actual Subscription, by a Customer, to a Product.

That makes sense and is actually what I thought it should be. The reason for my confusion was that the API is meant to pull in subscription data from subscribed users. Each user has a unique Subscription ID so I was looking for one “master” Subscription ID.

I thought that if I input an individuals subscription ID into the API’s URL then that will only relate to that one user, but of course, I am only trying to initialize it so any customers subscription ID will do!

I have now initialized the API successfully!

1 Like

Thanks for your help @adamhholmes. I will watch some tutorials on how to pull in data from the API and display on my site.

1 Like

@adamhholmes I realise this is a long thread but I am close to getting my API working, hoping you can spot what I may be missing!

I have successfully set up an API for users to manage their Stripe subscription (portal) using the following setup;

However, I’m still unable to receive data to display a users subscription Status? I am trying to do this with the following API setup;

Silly question but should I be including Parameters (Key and Value) to pull in bits of info, such as Status? If I do need to include Parameters I am unable to find how to, most info online mentions ‘key-value pairs’ but I don’t think this is what I need.

I am able to display the users payment Status if I pull data in from Bubble’s DB instead of Stripe, this is because when a user signs up I Create a new Subscription… as below;

Wouldn’t it be best to get the Status (and next payment date etc…) directly from Stripe rather than getting it from the above signup data? I am still not clearly seeing the bigger picture on how this all works.

What exactly is the issue you’re having?

I am able to display the users payment Status if I pull data in from Bubble’s DB instead of Stripe, this is because when a user signs up I Create a new Subscription… as below;

As long as your Bubble App Database is kept up to date with any changes of the User’s subscription (via your webhooks), then there’s no problem doing it that way.

There is just no communication with Stripe. It seems whatever I try I can’t ever get Stripe to ‘talk’ to my app.

For example, the following settings should return data;

But I see this when previewing my site;

2

As long as your Bubble App Database is kept up to date with any changes of the User’s subscription (via your webhooks), then there’s no problem doing it that way.

I’ve deleted my webhooks and all backend workflows because I’m trying to avoid using webhooks, you identified that the Stripe Plugin didn’t return data correctly, there’s a timing issue between the webhook running and the rest of the client side actions I’m running.

… hold on … do I need webhooks?

Webhooks are a way for Stripe to update my Bubble app but an API is a way for my Bubble app to constantly pull data from Stripe - so am I right in thinking we only need API calls (not webhooks)? If I use API’s to get up-to-date data from Stripe then are those API’s slowing the website down with constant calls?

Sorry to be a pain, but is there anyway you could give me a bullet list (overview) of what I need to do?

Are you sure you’re using a valid Subscription in the API call? Did the initial API call return any results when you initialized it the fist time?

In your screenshot in your previous post you’re using a static Subscription ID. Obviously in your app you’ll need to make that dynamic by adding square brackets in the URL.

UPDATE: Having just had a quick look at your app again, you’ve got an empty parameter set up in your API call - so as it is the call will fail - so you need to get rid of that (I’m not sure if that’s what the issue was before, but in any case you need to delete it)

you identified that the Stripe Plugin didn’t return data correctly, there’s a timing issue between the webhook running and the rest of the client side actions I’m running.

I was simply pointing out that you can’t search your database for Users based on a field that hasn’t been set yet (i.e. the customer ID, as when trying to set that via the plugin the webhook will have already run by the time the customer ID gets set in your database) - so you’ll need to use another way to identify the User on the backend.

… hold on … do I need webhooks?

That depends entirely on your app and what you’re trying to do…

But for a subscription app you’ll almost certainly need to use webhooks for some things.

Webhooks are a way for Stripe to update my Bubble app but an API is a way for my Bubble app to constantly pull data from Stripe - so am I right in thinking we only need API calls (not webhooks)? If I use API’s to get up-to-date data from Stripe then are those API’s slowing the website down with constant calls?

I’m not sure what you mean about making ‘constant’ API calls - you certainly don’t want to be doing that (especially as Stripe offers Webhooks - which takes away any need to make repeated API calls)…

Sorry to be a pain, but is there anyway you could give me a bullet list (overview) of what I need to do?

Although I don’t know exactly what you’re trying to do, from what I’ve gathered so far in your case this is what I’d do personally…

  • First I’d ditch any Stripe plugins and just use my own API call - (that way I can pass whatever custom metadata I need into the call, making everything on the backend super simple) - I’d continue to Use Stripe Checkout for simplicity (unless you want to integrate the whole payment process directly into your app)

  • Then, when a new customer signs up for a subscription, I’d create a Subscription in the database, and then, when you make the Stripe Checkout API call, add the unique ID of the Subscription from my database as metadata.

  • Then, I’d use a webhook to confirm the subscription has been created - and update the Subscription in my database accordingly (using the Subscription’s unique ID from the webhook metadata to identify the subscription) - and run any necessary workflows in my app.

  • Obviously you’d need to have other backend workflows and webhooks set up to handle things like failed payments, cancelled subscriptions, changes to subscription etc.

  • I’d still (personally) use Stripe API calls on any customer pages to show their subscription status, next payment date, and other payment details (as I’d be inclined trust it more coming directly from Stripe), but if you were confident in your own database, and happy that it’s been kept 100% up-to-date via your webhooks, then there’s no reason you couldn’t just show the data from your own database.

Thank you for your reply!

Are you sure you’re using a valid Subscription in the API call?

Yes, although it was a demo Subscription.

Did the initial API call return any results when you initialized it the first time?

Yes

In your screenshot in your previous post you’re using a static Subscription ID. Obviously in your app you’ll need to make that dynamic by adding square brackets in the URL.

I have just done this and now it’s asking for a Value?

UPDATE: Having just had a quick look at your app again, you’ve got an empty parameter set up in your API call - so as it is the call will fail - so you need to get rid of that (I’m not sure if that’s what the issue was before, but in any case you need to delete it)

Done.

I was simply pointing out that you can’t search your database for Users based on a field that hasn’t been set yet […] so you’ll need to use another way to identify the User on the backend.

Understood. This whole API/webhook setup is causing so much confusion for me I am in a muddle and forgetting things.

“… hold on … do I need webhooks?”
That depends entirely on your app and what you’re trying to do…

I’m not trying to do anything apart from say to a user “You are now subscribed” or “You are now unsubscribed”. My use case is literally the simplest any payment gateway can ever be.

But for a subscription app you’ll almost certainly need to use webhooks for some things.

Ok, that being the case I don’t see why I need API’s at all?

Although I don’t know exactly what you’re trying to do, from what I’ve gathered so far in your case this is what I’d do personally…

Thank you for your bullet points, I am going to work through them one by one.

I don’t know what custom metadata is. I am so sorry I think I need to pay someone to provide a dummy step-by-step with instructions.

I have been battling this for a month and the problem is I can’t see the bigger picture. I don’t know how to get over this hurdle. I will try your bullet points but I don’t know if I can do this.

Yes, in the value you need to enter the dynamic parameter value you want to put within the square brackets…

So you don’t put the whole URL in brackets - just the part you need to define dynamically, i.e.https://api.stripe.com/v1/subscriptions/[subscription_ID]

Then you enter a value for the ‘subscription_id’ - to initialize the API call you’ll need to enter a static, valid Subscription ID - but obviously when using the call in your actual app you’ll make that dynamic - i.e. Current User’s Subscription’s Subscription ID (or wherever it is you’re saving the subscription ID in your database)

note: you need to uncheck the Private box in order to be able to set the value dynamically in data calls in your app.

I’m not trying to do anything apart from say to a user “You are now subscribed” or “You are now unsubscribed”. My use case is literally the simplest any payment gateway can ever be.

If that’s literally all you’re trying to do then I don’t see any reason to be using any webhooks - you can just use an API call to get a user’s subscription status as and when you need it.

I don’t know what custom metadata is

Custom metadata is just any additional data, that isn’t part of any Stripe object, that you want to include in an API call - primarily for tracking purposes or so you can retrieve that data later on to make it simple to keep track of all number of things you might need to keep track of (such as the customer, the products/services/subscription, etc).

Thank you. This is a perfect example of why things are so hard for me, even this one step can be impossible to achieve.

I’ll explain why because I’m guessing many Bubbler’s know this feeling…

The layout on the API Connector is;

GET https://api.stripe.com/v1/subscriptions/sub_ywth****
Key:
Value:

As you’ve said I don’t put the whole URL in brackets - just the part you need to define dynamically. The trouble is, this could be any of the following;

GET https://api.stripe.com/v1/subscriptions/sub_ywth****
Key: https://api.stripe.com/v1/subscriptions
Value: sub_ywth****

GET https://api.stripe.com/v1/subscriptions
Key: https://api.stripe.com/v1/subscriptions
Value: sub_ywth****

GET [https://api.stripe.com/v1/subscriptions]
Key: https://api.stripe.com/v1/subscriptions
Value: [sub_ywth****]

GET [https://api.stripe.com/v1/subscriptions/sub_ywth****]
Key: https://api.stripe.com/v1/subscriptions
Value: [sub_ywth****]

These are all slightly different and I can think of more variations. I could test all of them, but when they all fail I will never know if the variation was wrong or if something else in the set up is wrong.

This is the same for many steps in the process, I never know why something failed because there are so many variables, the overall picture is too complex.

This is why I think I need painstakingly simple instructions, explained as you would to a 10 year old beginner, with images and explanations of what the steps are required for ie. why something is done. This is obviously too much to ask of you or anyone else without paying for your time.

If that’s literally all you’re trying to do then I don’t see any reason to be using any webhooks - you can just use an API call to get a user’s subscription status as and when you need it.

I had thought that I need to also show a message if the users card fails. In any case, going right back to the original problem, if a user unsubscribes I need to say “your subscription has ended and the last payment will be on xx/xx/xxxx” and this is why we started to set up the API.

I guess what I mean is that my requirements would be considered the most standard for a subscription service ie, subscribe, unsubscribe, get notified of status and if card has failed. I’m amazed that there isn’t a wealth of info online for this. I’ve done 20 tutorials but nothing comes close to explaining to a beginner all the steps needed.

I really don’t understand what you’re saying here at all?..

The URL remains the same - the only thing that changes is the Subscription ID

There are no variations - just the Stripe Endpoint URL (it’s always the same) - you just need to use change the subscription ID dynamically.

So as I said before: https://api.stripe.com/v1/subscriptions/[sub_ID]is the URL you need to use.

I had thought that I need to also show a message if the users card fails. In any case, going right back to the original problem, if a user unsubscribes I need to say “your subscription has ended and the last payment will be on xx/xx/xxxx” and this is why we started to set up the API.

I guess what I mean is that my requirements would be considered the most standard for a subscription service ie, subscribe, unsubscribe, get notified of status and if card has failed. I’m amazed that there isn’t a wealth of info online for this. I’ve done 20 tutorials but nothing comes close to explaining to a beginner all the steps needed.

You seem to be talking about two completely different things…

On the one hand you’re talking about ‘showing a message’ to a user - by which I’m assuming you mean show it on your app, on the page? In which case webhooks have got nothing to do with that (at least not directly).

For that you’ll either be making API calls to Stripe, OR referring to your own database.

But then you’re talking about ‘getting notified when a payment fails’ etc. - I’m not sure if you’re talking about you as the app owner getting notified, or the customer getting notified?

And I’m assuming you mean notify them via email, or some other direct message (rather than just a message on the page when they happen to be logged in and looking at your app)?

The question isn’t really clear - but if you are talking about notification via email/sms/ or even within your own apps notification system, then for that you’ll definitely need to be using webhooks.

If you’re just talking about displaying a message on the screen when a user is looking at your app then you don’t (directly) need to use any webhooks for that at all (you might need to use webhooks to set the data in your database, if you’re referring to that rather than making API calls to Stripe).

So, I’m not entirely sure which of the two you’re trying to do, or possibly both, or if you’re even clear of the difference?

But, more than likely you’ll want to be using both…

API calls so you can get data from Stripe when you need it.
And webhooks so you can do things in your app when certain things happen in Stripe.

If that is the URL then I don’t know what the Key or Value is. I am so lost and not enjoying this so I need someone to do it for me, or provide a step-by-step instruction (I don’t mind paying).

I am sorry @adamhholmes as I know you’ve given a lot of your time but I’m going in circles.

API calls so you can get data from Stripe when you need it.
And webhooks so you can do things in your app when certain things happen in Stripe.

If I wanted to know that a user had unsubscribed that would require a webhook. But also an API call would fetch that data so I still don’t see the need for both.

Apologies for my vagueness, here is explicitly what I am trying to do;

Thing to achieve 1
User logs into my app where I display Text saying “You are NOT subscribed”.

Thing to achieve 2
User clicks subscribe from within my app and goes to Stripe
User fills out card details and subscribes
I display Text on my app saying “You are subscribed”.

Thing to achieve 3
User payment is declined
I display Text on my app saying “Your payment was declined, please update card details”.

Thing to achieve 4
User clicks unsubscribe from within my app and goes to Stripe
User clicks unsubscribe within Stripe
I display Text on my app saying “You have unsubscribed but you can still enjoy using the app until xx.xx.xxxx”.

That last Text sentence is the hardest and no one has been able to explain how to do it. You did explain it’s possible with a complex arrangement of backend workflows using API’s but it’s too difficult (for my level).

I’ve found that there are many ways to set up subscriptions which makes is so difficult to learn as every tutorial is different.

The closest I got to success was with the Stripe Plugin following this video. I was not able to display text when a user unsubscribes but maybe I could pay someone to just do that one job. I’m not sure.

I think the problem for me is the scope of the task … an analogy is how I am very comfortable with complex options trading on the stock market, but if someone wanted to learn I could not teach them much because they’d need to be able to zoom out and understand the way things work as a whole. This is the same thing, I feel I am constantly getting lost and can’t grasp the full picture, despite your excellent instructions - I need a step-by-step tutorial which includes everything I am trying to achieve … if anything is missing from the tutorial I am not able to work it out because every tutorial is wildly different.

They key is just the name/identifier of the parameter (it can literally be anything you want to call it). And the value is the value of that parameter (i.e. the Subscription ID).

So, again, the URL can be https://api.stripe.com/v1/subscriptions/[sub_ID]

In this case the Key is sub_ID - but you can call it anything you like (subscription_ID, parameter1, URL Path, Mr Smith - literally anything, it makes no difference) , although obviously something descriptive, that you’ll recognise when you need to define it on your pages, is the most sensible thing to do.

And the value is, in this case, a Subscription ID. On your pages that will obviously be a dynamic value (i.e. the ID of the particular subscription you’re trying to retrieve), but in the API connector, in order to initialize the call, it has to be a specific valid Subscription ID.

Thing to achieve 1
User logs into my app where I display Text saying “You are NOT subscribed”.

Thing to achieve 2
User clicks subscribe from within my app and goes to Stripe
User fills out card details and subscribes
I display Text on my app saying “You are subscribed”.

Thing to achieve 3
User payment is declined
I display Text on my app saying “Your payment was declined, please update card details”.

Thing to achieve 4
User clicks unsubscribe from within my app and goes to Stripe
User clicks unsubscribe within Stripe
I display Text on my app saying “You have unsubscribed but you can still enjoy using the app until xx.xx.xxxx”.

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 (although obviously, if you’re getting it from your own database instead then you’ll need to use webhooks, or I suppose recurring API calls, to set that data in the first place).

Although, at this point I’m really not sure I really understand your app, or what your users are paying for?..

Surely your customers are paying for more than just a message saying “You are subscribed”? Surely they’re getting more than that in return for their subscription payment? (other things must be required to happen upon successful payment, surely?)

And if their payment fails, all that happens is they see a message saying “Your payment was declined, please update card details”? So where’s the incentive to pay? What are they paying for exactly? And what will they lose if they don’t pay?

And if they unsubscribe, and cancel their payment, nothing happens apart from they see a message saying “You have unsubscribed but you can still enjoy using the app until xx.xx.xxxx” (surely they’ll lose access to your app after that?)

So, surely you’re going to need to use webhooks to manage all of that?