Has anybody integrated Stripe payment gateway WITHOUT plugins? only using API connectors

I checked the Bubble stripe plugin and I found it basic and buggy, then I thought about using StripeJS plugin but the guy is no longer supporting that plugin so I don’t want to end with an integration that doesn’t work in the future.

So I decided to do it purely via API connector…

I started reading the stripe convoluted API documentation and I was able to create express accounts, link account yadda yadda but I cannot make CHECKOUT work (their basic )

create checkout session->redirect to checkout

Any success stories? or a good samaritan who can guide me? I have spent literally a week fighting with Stripe

thanks a lot!


Hello @natserrano

I had created a few functions at the beginning but found that the stripe.js plugin has the majority of the required functions and is regularly updated. It should not be forgotten that the plugin code is available when needed.

Hi @natserrano,

Using Stripe’s Checkout is simple using the API connector, and far more flexible than using any plugin.

As you say, you first have to create a checkout session, and then redirect the user to the checkout.

  1. Creating A Stripe Chekout Session

First, make sure you’ve got your Authentication setup correctly for the Stripe API:

Then you need to make the API call to create the session.

Make a post request to https://api.stripe.com/v1/checkout/sessions

Make sure you set it as an ‘action’ with the body type ‘json’, and add the required parameters (they need to be set as querystrings). See below:

See the Stripe Checkout ‘Create a Session’ API doc for full details of all the parameters (note some of them are required, some are optional).


The only other thing to know about here is the format that parameters need to be entered into the API connector for them to work…

For basic parameters (e.g. ‘success_url’) just enter them as they appear in the Strip API doc ‘success_url’.

For nested parameters (e.g. ‘line_items.price_data.unit_amount’) they need to be written with all subsequent parameters, after the first one, inside square brackets, including an empty set of square brackets to indicate an array.

So, for example, the parameter: line_items.price_data.unit_amount
should be written in the API connector as: line_items[price_data][unit_amount]

When the call is run it will return a ‘Checkout Session ID’ which you’ll need to use in the second step.

  1. Redirect to Checkout

You’ll need to run some java script for this, so make sure you’ve got a plugin installed that allows you to do that (i.e. toolbox).

Just run the following script:

var stripe = Stripe('pk_test_***');

sessionId: 'Result of Step 1 - Checkout Session ID'})
.then(function (result) {

Where ‘pk_test_***’ is your publishable Stripe API key
And ‘Result of Step 1 - Checkout Session ID’ is the Session ID returned from the ‘create session API call’ in step 1.

*Note: you’ll need to set up separate redirects for Live and Dev versions of your app, using the appropriate API keys and some conditions (i.e. only when ‘isn’t live version is yes’, only when ‘isn’t live version is no’).

The whole process should run as follows:

When a user clicks on your ‘pay now’ button (or whatever triggers the checkout process) just run a workflow with 3 steps:

  1. Creat the checkout session
  2. Run the Redirect Java Script (Dev version only)
  3. Run the Redirect Java Script (Live version only)

See below for how mine is set up:

Hope that helps


Oops, I forgot to add that you’ll need to add the following script to the page HTML header of whichever page the workflow is run from in order for the javascript call to work:

<script src="https://js.stripe.com/v3/"></script>


thank you Adam!, my issue was that I was authenticating using HTTP basic auth,

also the ability to use JS with toolbox will come really handy!

now I will try to make it work with Subscriptions and price tiers, wish me luck, thanks again!


I also implement Stripe with the API connector.
I am a non tech, it’s a bit tricky at the beginning but very quick and way more flexible when you understand how it works.
Plus, as stripe makes a lot of updates, regarding technical and legal things, you can update faster when needed. And it feels better than relying on plugin maker. Even if plugins are very simple to use and the API takes some time to set up, I finally feel way more confortable doing it myself.

For every action you take with Stripe, don’t forget to set Webhooks. Rely on Stripe’s webhooks to make any changes to your users or data fields.
For example, to confirm a payment after checkout, don’t do it during the initial workflow, and prefer to listen to Stripe « checkout sessions complete » webhook. You can then do a backend workflow editing your data’s. It’s quicker, and more secure.

With pleasure to chat about Stripe topics if you want. ( I am not a pro, but interested to talk about other bubblers using the API connector)


Yep, I definitely agree about using webhooks to confirm payments have gone through.

Don’t just rely on running workflows from the ‘thank you’ page for confirmation, as that’s not 100% reliable - people can end up there who haven’t made a purchase, or return there after they’ve already been there - giving you false or duplicate transaction records in your bubble database - or may have connectivity issues, so never end up there even though they’ve paid.

Webhooks are simple to set up and much more reliable.


Were you able to use the api connector and checkout with multiple prices? This is where I’m stuck right now. This call works fine in Postman (meaning I receive the correct total) but not in Bubble. (Please note that the price ids appear identical in the screenshot, but in the editor, when scrolled to the right, they are indeed unique from each other).

My editor is viewable here B2b-checkout | Bubble Editor

Solved (Create a Session | Stripe API Reference)

For multiple products, you simply number the line_item array


Check here maybe. Technically, it’s a plugin, but it’s built without code - i.e. using the same UI as the API Connector. (Calls built using the API Connector plugin can be converted to their own plugin.)

1 Like

Hi, I’ve run into a snag where I get a “Stripe not defined” error if I have it in the Page HTML Header

It works if I put the <script src > in an html element but then I get all sorts of security warnings.

The editor is viewable here:

Any ideas?

Ok, so this may be only available for paid plans (putting a in the header), but I don’t think it’s necessary as the POST request returns all the values I need. :crossed_fingers:

*hopefully solved – Using the Plugin “Stripe Connect Checkout” https://bubble.io/plugin/stripe-connect-checkout-1587126282427x307730754949087200
Getting console errors but the redirect is now working…

Heads up!
I just run into general error with JS redirecting to Checkout. The solution was to uncheck “asynchronous”

And just wanted to say thanks @adamhholmes for the solution


Hi @banbimmo and @adamhholmes,

I am using the api connector to subscribe users, delete cards, apply tax rates, etc… can you explain in more detail what the webhooks are, the advantages and especially how I can set them up with Bubble and Stripe. I currently don’t know if a payment or subscription has gone through, I think Webhooks was the missing peace, but I am clueless as where to start. Do you have a demo or something you can show or the steps needed.

I just managed to apply VAT to stripe subscriptions and was pretty happy with the result, but I’m missing this important part on Webhooks.


1 Like

Hi !

Quick long answer here to help you, sorry maybe it will not be very structured.

  • get in mind I am not a professionnal devloper, sometimes I may say some stupid or very non technical stuff :slight_smile:

Webhooks are a way to send back information from a solution to another, when an event occured.
If you ask Stripe to do something via the API, you will get a response saying “I receive your demand, and will do that”. So that’s the “200” code the api return when you do something through the API.

Then Stripe does what you asked. And you have to know if it’s done or if a problem occurs.
(OR, sometimes, events happened and Stripe have to let you know (for example if one of your user’s credit card expires 6 months after he subscribed…)

When this is done, you need to know it is done, as you say. So Stripe can send webhook.
So webhooks are secured and reliable call that let you know that something went well, or not.
What I love with Stripe + bubble API Connector is that you can easily (really in 1 minute) set webhooks, for pretty much everything in Stripe (When a payment is completed, when you need to be aware of something like required infos about a customers or a connected account, etc etc…).

To set webhooks, there are two important step :

  • You have to create an endpoint in your bubble app (I don’t know how devlopers describe it, but I like to say, it is exactly like a phone number or an email adress… people who need to contact you know they have somewhere to send an info to.) :
    In your bubble app : you can set it up in the backend workflow tab (avalaible in the editor, at the bottom of your pages list. If not available, you have to enable backend workflows in your app setting -> API.)
    So Just create an endpoint like “CheckoutSessionCompleted” . Once you have it : double click on it, click on “detect data”, copy the link.
  • Create a webhook in your Stripe dashboard -> Devlopers -> Webhooks, create new webhooks.
    Paste the adress.
    Select the event you need to send with this webhooks.

Your are all set up ! Almost…

You have to initialize it by sending a test webhook. Back to Bubble you can check your endpoint received it. And then, remove the “initialize” in the adress from your stripe dashboard, to make it work.

Please note that there are different authentification parameters enabled, and you have to be careful about it. There are some topics on the forum about it. For my usecase, I asked to the bubble support if it was allright and secure and they did answer.

What will happen then ?
Some examples :
When a user subscribe, you process the checkout. -> When payment is completed, Stripe send a webhook to your endpoint -> You can listen to this endpoint and automate a new workflow (for example -> changing the users datas as “subscribed” -> sending a welcome email etc…
At the end, instead of saying : " Someone checkouts, it looks like the payment goes well because he came back at the success url, so I will confirmed he subscribed"… (What is not secure because a users just has to know what is the success url to be subscribed…), you will say “Ok the users processed the checkout, and I am Sure the payment went well because Stripe sent me the confirmation of the payment through the webhook… So at the second I receive the webhook, the users will be marked as subscribed and I will confirm him by email.”

You can set webhooks to listen to other events, and it is very powerfull. For example if you use subscription. Saying one users subscribes, and his credit cards expire 6 months later. I you set the right webhooks, Stripe will send you an event 6 months later to say “I can’t process this payment, because the customer credit cards is expired”, and you can automate workflows easily, for example -> When payment fails, change the user as unsubscribe, send him an email to come back and update his credit cards…

You have to create webhooks for every important actions and events. From my understanding this is key to the app health and security…

Hope it will helps you !


Thanks @banbimmo for the detailed explanation!

Currently I use conditions to show confirmation message if Stripe subscription exists for that particular user. When payment goes through I refresh the page and connect to Stripe through the API Connector to see if a subscription exists. If subscription count is 0 I don’t show the confirmation message (Using conditionals). Is this a fare way to build this? It’s basically the other way round, Bubble connects to Stripe through the API to check if the subscription has gone through. What are the disadvantages of Bubble connecting to Stripe to see if a payment has gone through rather than the other way round, Stripe connecting to Bubble to confirm the payment has gone through? Not sure if I have explained my self very well, just trying to understand this.

I have a question about the endpoints. How do you see if you are receiving correctly the webhook in your endpoint? Is it just by the result of automating a Workflow or is there some kind of place or log where you can see if the endpoint is receiving the webhook from Stripe?

I will try it out. Thanks again, this info is of great help.

It’s basically the other way round, Bubble connects to Stripe through the API to check if the subscription has gone through. What are the disadvantages of Bubble connecting to Stripe to see if a payment has gone through rather than the other way round, Stripe connecting to Bubble to confirm the payment has gone through? Not sure if I have explained my self very well, just trying to understand this.

Got you.
I am not a specialist about subscriptions as I only use One time payments.
But I believe you could have an unpaid subscription ? So the subscription is created and exist but payment_intent failed ? So you will have to save the payment intent ID related, refresh the page, retrieve the payment intent, and apply your conditions ? Something like that ?
My guess, again I am not a tech, is that it should work, but looks like the unlogical way to me, maybe affecting performance / Speed / security ?
I also believe that it will be a nightmare to process and automate others actions (if you need it) and a new workflow to confirm to your users the subscription (sending an email, sending the invoice, changing one of your users data field). And I guess, at least, you have to save somewhere in your data that the users subscribed.
You will have to check if the subscription exist and is paid when page is refreshed, meaning when page is loaded, meaning it would affect your initial page load.
Maybe other needs I dont think of right now.

Stripe, generally speaking, recommend the use of webhooks for asynchronous events, this is the case for subscriptions : Use incoming webhooks to get real-time updates | Stripe Documentation

I have a question about the endpoints. How do you see if you are receiving correctly the webhook in your endpoint? Is it just by the result of automating a Workflow or is there some kind of place or log where you can see if the endpoint is receiving the webhook from Stripe?

You can check webhooks in your stripe dashboard, it shows you errors rate per webhooks (dashboard → Dev → Webhooks → at the right of the screen)…
Also, Stripe email you when there’s a high error rate, or when a specific webhook return an error code to Stripe (for something like 2 or seven days).

I believe we are speaking of a new specific topic, DM me if you want. + I think, reading your last message, you did something I am not able to do, so maybe we could help each other :wink:


Thanks again @banbimmo. I’m starting to understand the power of webhooks. I’m changing my whole Checkout process as we speak. The power of just using the API and webhooks is awsome!

I’m stuck on this bit though. when I remove the ‘initialize’ from the address it doesn’t work and I’m getting an “Unauthorized, You must authenticate to call this method” response from Stripe. Do you know what I am doing wrong? Should I be including the secret key somewhere in bubble or something?

Hi @banbimmo,

I just clicked " This endpoint can be run without authentication" and it works now.

This means bubble send an error back to Stripe, saying there’s no authentification.

You either have to :

  • Build the authentification, see Stripe and bubble references about it (and stripe webhooks best practices/security ), way too long to explain.
  • Check the “run without authentification”. But be very careful about it regarding security. It means anybody can send something to your endpoint and could activate a workflow if they have the right info, could be a breach.
    So if you are using it, you have to be 100% sure that your following workflows uses Datas nobody could use/have (a user unique ID, a payment unique ID nobody has access to…). You can use Stripe Ids, or a personnal system.
    In your subscription workflow, it could be the customer IDs saved in your bubble Datas. When you receive the webhook -> Make a chenge to a user -> Do a search for users : Data’s request customer ID = Your users data Cust ID -> Then change this. It then would be hard for anyone to activate the workflow if your Cust ID are not available to anyone. But I think you have to look for higher security options, Stripe recommand to check webhooks’ Timestamp also I remember.

Again, I am not a techy, and I advise you maybe to ask to Bubble support or devlopers if you use the "run without auth option.