Bubble Docs
  • Introduction
  • New? Start Here
  • What is Bubble?
  • The Glossary
  • User manual
    • Getting started
      • What is Bubble?
      • Building your first app
        • Planning features
        • Database structure
        • Design and UX
        • eCommerce and payments
          • Shopping cart
          • Checkout page
          • One-time payments
          • Subscriptions
          • Marketplace
      • Creating and managing apps
      • The Bubble editor
        • Tabs and sections
          • Design tab
            • The element tree
            • The property editor
          • Workflow tab
          • Data tab
          • Styles tab
          • Plugins tab
          • Settings tab
            • Application settings
              • Custom headers/body
              • Visual settings
              • Social media sharing
              • Translating your app
              • Email settings
              • Collaboration
            • Custom domain and DNS
          • Logs tab
        • Tools
          • Key features
          • The search tool
          • The Issue Checker
          • The element tree
          • The element property editor
          • The debugger
          • Notes
        • Previewing your app
      • Transitioning to Bubble from...
        • JavaScript
        • HTML and CSS
        • SQL
    • Design
      • Elements
        • The element hierarchy
          • The element tree
        • The page
        • Containers
          • Groups
          • Repeating groups
          • Table elements
          • Popups
          • Floating groups
          • Group focus
        • Visual elements
        • Input forms
          • Text and numbers
          • Dates and time
          • File uploads
          • Selection controls
        • Reusable Elements
      • Styling
        • Color variables
        • Font variables
        • Styles
        • Custom Fonts
      • Responsive design
        • Building responsive pages
        • Legacy articles
          • The Basics (Legacy)
          • Building Responsive Pages (Legacy)
          • Migrating Legacy Pages
          • Tips When Designing (Legacy)
      • Templates
      • The Component Library
      • Importing from Figma
    • Data
      • The database
        • Data types and fields
        • Creating, saving and deleting data
        • Finding data
        • Displaying data
        • Protecting data with privacy rules
        • The database editor
        • Export/import data
          • Exporting data
          • Importing data (CSV)
        • Working with location data
        • Using Algolia
        • Database structure by app type
          • Marketplace Apps
          • Directory & Listings Apps
          • Social Network Apps
          • SaaS Apps
          • Project Management Apps
          • CRM Apps
          • Professional Services Apps
          • On-demand Apps
          • Documentation/ CMS Apps
          • Applicant Tracking System (ATS) Apps
          • Portfolio Apps
          • Gallery Apps
          • Online Store / Ecommerce Apps
          • Blog Apps
          • Messaging App
          • Dashboards
          • Building Block Apps
          • Bubble as a backend
      • Files
      • Images
      • Static data
        • App texts (translations)
        • Option sets
      • Temporary data
        • Custom states
        • URL parameters
      • User accounts
        • Authentication plugins
          • Facebook plugin
          • Fitbit plugin
          • Google plugin
          • Instagram plugin
          • LinkedIn plugin
          • Pinterest plugin
          • Slack plugin
          • Wistia plugin
          • YouTube plugin
        • Cookies set by Bubble
      • Time, dates and time zones
    • Logic
      • The frontend and backend
      • Workflows
        • Events
          • Frontend events
            • Recurring workflows
            • Custom events
          • Backend events
            • Database trigger events
        • Actions
        • API Workflows
      • Dynamic expressions
      • Conditions
      • Navigation
        • Single-page applications (SPA)
        • Multi-page applications
        • Page slugs
    • Workload
      • Understanding workload
        • Activity types
        • The workload calculation
        • Client-side and server-side processing
      • Tracking workload
        • Measuring
          • Using App Metrics
        • Monitoring
          • Workload notifications
          • Infinite recursion protection
      • Optimizing workload
        • Optimization framework
        • Optimization checklist
          • Page load
          • Searches
          • Workflows and actions
          • Backend workflows
        • Agency showcases
          • Minimum Studio
          • Neam
          • Support Dept
    • Security
      • Bubble's security features
      • Planning app security
      • Client-side and server-side
      • Bubble account security
      • App security
      • Page security
      • Database security
      • API security
        • API Connector security
        • Data API security
        • Workflow API security
      • Flusk
        • Overview
        • Flusk plan features
        • Getting started with Flusk
        • Flusk security tools
          • The Issues Explorer
          • Issue details
          • Tools and settings
            • Pages rating
            • Database rating
        • Flusk FAQ
      • Cookies
      • Security checklist
    • Publishing your app
      • Web app
      • Native mobile app
        • Global native mobile settings
        • iOS App Store
        • Google Play Store
        • Publishing FAQ
    • AI
      • Generate apps with AI
        • About AI app generation
      • AI page designer
      • Connect to AI agents
    • Maintenance
      • Collaborators
      • Version control
        • Best practices: Version control
        • Transitioning from the legacy version control
        • Terminology: Version control
        • Version Control (legacy)
      • Commenting
      • Database maintenance
        • Copying the database
        • Restoring database backups
        • Bulk operations
          • Bulk operation methods compared
        • Wiping change history
      • Performance
        • Hard limits
        • Capacity Usage (legacy)
        • Notes on queries
      • SEO
        • Introduction to SEO
        • SEO: App
        • SEO: Page
      • Testing and debugging
        • Introduction to testing and debugging
        • The debugger
        • The server logs
        • Supported browsers
      • API workflow scheduler
    • Integrations
      • API
        • Introduction to APIs
          • What is a RESTful API?
        • The Bubble API
          • Bubble API terminology
          • Authentication
            • How to authenticate
            • No authentication
            • As a User
            • As an admin
          • The Data API
            • Data API Privacy Rules
            • Data API endpoints
            • Data API requests
          • The Workflow API
            • Workflow API privacy rules
            • Workflow API endpoints
            • API workflows
              • Creating API workflows
              • Scheduling API workflows
              • Recursive API workflows
              • API Workflow Scheduler
              • Case: Stripe notifications
        • The API Connector
          • Authentication
          • API Connector security
          • API guides
            • OpenAI
              • Authentication
              • Calls
                • ChatGPT
                  • Chat
            • Google Translate
              • How to setup Google API keys
          • Streaming API
        • API security
        • Plugins that connect to APIs
        • API Glossary
      • Plugins
        • What Plugins Can Do
        • Installing and using Plugins
        • Authentication plugins
        • Special Plugins
      • SQL Database Connector
      • Bubble App Connector
      • WorkOS
        • WorkOS SSO
        • WorkOS API
    • Infrastructure
      • Sub-apps
      • Bubble release tiers
      • Hosting and scaling
        • How Bubble hosting works
        • Scaling with Bubble
        • CDN (Cloudflare)
        • Bubble app names
        • Domain and DNS
      • Compliance
        • GDPR
        • SOC 2 Type II
        • HIPAA
        • Other frameworks and standards
    • Bubble for Enterprise
      • Hosting and infrastructure
        • Dedicated instance
          • The Dedicated editor experience
          • Technical specs
          • Main cluster dependencies
          • Customizable options
          • Migration process
            • Pre-migration
            • During migration
            • Post-migration
      • Security and compliance
        • Single sign-on (SSO)
        • GDPR
        • SOC 2 Type II
        • HIPAA
        • Other frameworks
        • Bubble's security features
      • Admin and collaboration
      • Priority support
      • Billing and Payment Guideline for Dedicated Instances
  • Core Reference
    • Using the core reference
    • Bubble's Interface
      • Design tab
      • Design tab (Legacy)
      • Workflow tab
      • Data tab
      • Styles tab
      • Styles tab (Legacy)
      • Plugins tab
      • Settings tab
      • Logs tab
      • Template tab
      • Toolbar
      • Top and context menu options
      • Deployment and version control
        • Deployment & Version Control Dropdown (legacy)
      • Notes
    • Elements
      • General properties
      • General properties (Legacy)
      • Styling properties
      • Styling Properties (Legacy)
      • Responsive Properties
      • Responsive Properties (Legacy)
      • Conditional formatting
      • States
      • Page Element
        • Page Element (Legacy)
      • Visual Elements
      • Containers
      • Container Layout Types
      • Containers (Legacy)
      • Input Forms
      • Reusable Elements
      • Element Templates (legacy)
    • Workflows
    • Events
      • General events
      • Element events
      • Custom events
      • Recurring event
      • Database trigger event
    • Actions
      • Account
      • Navigation
      • Data (things)
      • Email
      • Element
      • Custom
    • Data
      • Data Sources
      • Operators and comparisons
      • Search
      • Privacy
    • Styles
    • API
      • The Bubble API
        • The Data API
          • Authentication
          • Data API endpoints
          • Data API requests
        • The Workflow API
      • The API Connector
        • Authentication
        • Adding calls
    • Bubble-made Plugins
      • AddtoAny Share Buttons
      • Airtable
      • API Connector
      • Blockspring
      • Box
      • Braintree
      • Bubble App Connector
      • Chart.js
      • Circle Music Player
      • Draggable Elements
      • Dropzone
      • Facebook
      • Fitbit
      • Full Calendar
      • Google
      • Google Analytics
      • Google Optimize
      • Google Places
      • Ionic Elements
      • iTunes
      • Slidebar Menu
      • LinkedIn
      • Localize Translation
      • Mixpanel
      • Mouse & Keyboard Interactions
      • Multiselect Dropdown
      • Progress Bar
      • Rich Text Editor
      • Rich Text Editor (Legacy)
      • Screenshotlayer
      • SelectPDF
      • Slack
      • Segment
      • Slick Slideshow
      • SQL Database Connector
      • Star Rating
      • Stripe
      • Tinder-like Element
      • Twitter
      • YouTube
      • Zapier
    • Application Settings
      • App plan
      • General
      • Domain / email
      • Languages
      • SEO / metatags
      • API
      • Collaboration
      • Sub-apps
      • Versions
  • Account & Marketplace
    • Account and billing
      • Pricing and plans
        • Plans and billing
        • Billing cycle
        • FAQ: Pricing and Workload
      • Account Management
      • Building Apps for Others
      • Selling on the Marketplace
      • Plans & Billing (legacy)
    • Official Bubble Certification
      • Hiring certified developers
    • Building Plugins
      • The Plugin Editor
      • General Settings
      • Updating to Plugin API v4
      • Adding API Connections
      • Building Elements
      • Building Actions
      • Loading Data
      • Publishing and versioning
      • Github Integration
    • Building Templates
    • Application and data ownership
    • Marketplace policies
    • Bug reports
  • Vulnerability Disclosure Policy
  • Beta features
    • About the Beta features section
    • Native mobile apps 🔒
      • Introduction
        • What is a native mobile app?
        • Native mobile vs. web development
        • Differences in native and web elements
        • Native mobile app terminology
      • Building
        • Views and navigation
        • Native mobile actions
        • Components and gestures
        • Device resources
          • Location services
          • Camera/photo library
      • Previewing
      • Publishing
Powered by GitBook
On this page
  • Notifying users when a Stripe subscription charge fails
  • Sending a monthly newsletter
  • Writing a script to read data from the database

Was this helpful?

  1. User manual
  2. Integrations
  3. API
  4. The Bubble API
  5. The Workflow API
  6. API workflows

Case: Stripe notifications

Last updated 12 months ago

Was this helpful?

As the API is a way to let external services connect to your app, each case has a different implementation. Here are 3 different examples of how to use the Bubble API in real-life. Note that each example assumes that the app is on a paid plan and the APIs are activated.

Notifying users when a Stripe subscription charge fails

Having your app take some actions when something happens on another service's end is a typical use case of the Bubble API. This will walk through the different steps, both on Bubble's and Stripe's sides. We'll start with an app that already has the Stripe plugin installed, with the relevant keys entered in the Plugins Tab. We also assume that our payment workflows save the Stripe customer ID of the user on the user - we'll need it to go from the ID Stripe provides to the User thing, and get his/her email.

We assume for this example the domain of the app is

https://stripeexample.bubbleapps.io

We'll start on the Bubble side, in the Backend Workflows page accessed via the page navigator in the topnav. We need to define an API Endpoint that will be called whenever Stripe fails to charge a credit card. This API workflow should have an action that sends an email to the customer with a message prompting him or her to update his card. So let's start by creating a new API Event that we'll call 'chargefailed'.

We make this endpoint public, so that Stripe can trigger it via a webhook (see below), and we make it possible to run without authentication for simplicity.

We can now start building the Send Email action. We need to do a few things:

  1. Use a Send email action to send an email to this user.

  2. Perform a search in Bubble to retrieve the user with this customer ID.

  3. Write a friendly reminder.

We start by adding the action, and will work on the To field. In this process, it's important to think from what we need and go up from there. Therefore, we start with the search for Users, add a constraint on the Customer ID field, and define the value as the result of an API call from Stripe. Here is the search.

To get the Customer ID of the prevent event. The Stripe plugin offers a call to retrieve an Event object from an Event ID. Doing a call to Stripe will validate the Event ID, and will return the Event object. From this object, we can get the Stripe Customer ID. So what we need here is the data source 'Get Data from an API'.

The API call is 'Get Stripe event', and the event_id we need to send to Stripe is precisely the one we got from the initial request (the webhook). This parameter is the first entry in the dropdown, we select it.

At this stage, we have retrieved the Stripe Event object, we just need to get the Customer ID and our search will be ready.

We can get back to the To field of the 'Send Email' search, and get the email of the user. Note that a search returns a list of users. In this case, we know the customer ID is specific to each user, but we need to get the first item of the list, to go from a list of one user to the user, and then get the email.

We can now finish the action by adding the message we want to send.

We're all set on Bubble's side. Let's summarize what our workflow does:

  1. Get the Event ID sent by Stripe with the webhook

  2. Fetch the Event object and get the Customer ID

  3. Perform a search in the application's database and get the user with this Customer ID

  4. Send an email to the user that was retrieved by the search.

The full endpoint for this workflow is:

https://stripeexample.bubbleapps.io/api/1.1/wf/chargefailed

And we're all set! Whenever a charge fails, the webhook is triggered, and Bubble will send an email to the user. You can see the execution of such workflow in your server logs.

Sending a monthly newsletter

This example shows how you can create a system where your users can opt-in and opt-out for a weekly email. We'll cover the logic and the workflows to set up a weekly action, the content of the email will not be covered.

First, we head to the API page of our app and create a new recurring event.

Let's call this event 'Newsletter'. A newsletter subscription is attached to a user, so we pick user as a type of thing.

This workflow will have one action that sends an email to the user that is sent to this workflow (the 'Current Workflow User')

We can now move to the page in your app where we'll offer users the option to opt-in or opt-out from this newsletter. We'll do this in a very simplified 'account' page that shows two buttons.

We need to add two workflows to our page. We assume that in this page, the user is logged in, and won't worry about enforcing this in the example-page.

The first workflow will let users opt-in. It is triggered when the user clicks on the button 'Opt-in', and will use the 'Set/Cancel a recurring event'.

This action takes an event and a thing. In this case, the event is 'Newsletter', and the thing is the Current User. We built the workflow so that the newsletter is sent weekly, starting on the following day at 9am.

The opt-out workflow shares exactly the same structure, except that the frequency will be 'none'. Effectively, this will cancel any scheduled recurring event (and won't do anything if no event is scheduled initially).

Writing a script to read data from the database

The GET/Data API lets you read your data programmatically. This can be done by another application, but can also be used in some scripts to save or print your data. This example shows how you can do this in Python. We're writing this script for an app hosted on the domain yourapp.com, and our goal is to retrieve all invoices. This assume that our app has a type named 'invoice'. We do not add constraints, but it would be easy to add such constraints, as described in the reference.

The key concept in such a script is the pagination. When you make a request to the API, you need to define where to start, and a number of items to fetch. Each response from the GET API will return the number of remaining items. In our example, we want to start at the last item of the previous call plus one.

#packages to perform the request, handle JSON objects, and encode URLs
import requests
import json
import urllib

session = requests.Session()

#API KEY as defined in the settings tab, so that the script has full access to the data
API_KEY = 'XXXX'
#base endpoint, see https://bubble.io/reference#API.get_api.Endpoint
base_url = 'https://yourapp.com/api/1.1/obj/invoice'

#Query initial parameters. We do not send a limit parameter (default is 100)
cursor = 0
remaining = 100

#we keep making calls till we have no remaining items to fetch
while remaining > 0:
    #data we send with the search. Search constraints would be here
    params = {'cursor': cursor, 'api_token': API_KEY}
    url = base_url + '?' + urllib.parse.urlencode(params)
    response = session.get(url)

    if response.status_code != 200:
        print('Error with status code {}'.format(response.status_code))
        exit()

    chunk = response.json()['response']
    remaining = chunk['remaining']
    count = chunk['count']
    results = chunk['results']

    #we print each object
    for result in results:
        print(json.dumps(result, indent=4, sort_keys=True))

    cursor += count

print('No more entries')

Such a script can be used (and adapted) to save data instead of printing it, query some data that fits some constraints, etc.

Looking at Stripe's shows what Stripe sends when it triggers a webhook. Stripe's server will make a request to our endpoint, and send an event ID in the body in the request. Therefore, we're adding an id parameter to our call of type text.

Use the Event ID sent by Stripe to retrieve the . This event contains the charge object and the customer ID.

We're now heading to Stripe to configure the webhook. What we want: whenever a charge fails, trigger a webhook to this URL. We do this in .

documentation
Event object
here