In this tutorial, you will integrate with Stripe to automate subscription payments in your app. You will define your subscription-based pricing plans and set up corresponding Stripe products and prices. At the end of this tutorial, users of your app will be able to sign up for a specific subscription directly from your pricing page, switch between pricing plans after signup, and update their payment methods.

This tutorial assumes you have already set up authentication with Auth0 since all dashboard interactions that involve subscriptions happen in the context of an authenticated application user.
Now, let's get paid!
We are using Stripe as the payment processing and subscription management platform. If you don't have a Stripe account, you can create one here.
We use Stripe CLI to tunnel webhook events related to payment and subscription lifecycle to your locally running application. Follow the instructions here to install and set up the Stripe CLI.
For the purpose of this tutorial, we exclusively use Stripe's test mode intended for development and testing. Stripe's test mode does not affect the flow of actual money and has its own set of API keys separate from production. Setting up the live Stripe environment generally follows the same steps, except where indicated.
You will need three keys: publishable key, secret key, and the webhook signing secret.
You can access the publishable key and secret _key for Stripe's test mode from Test Mode API Keys section of the Stripe dashboard.
To access the webhook signing secret, you must first register a new webhook endpoint with Stripe:
- Determine the base URL of your API server running in AWS by executing
yarn ops status -a api
. The Url property contains the API base URL. - Go to the Test Mode Webhooks page of the Stripe's dashboard and choose Add endpoint in the Hosted endpoints section.
- In the Endpoint URL, enter
{base-url}/v1/stripe/webhook/test
, where{base-url}
is the API base URL you determined above (NOTE when setting up live Stripe environment, you need to enter{base-url}/v1/stripe/webhook/live
for the Endpoint URL). - Click Select events and check the checkbox next to select all events. Then click Add events.
- Back on the previous screen, click Add endpoint.
- You will now see a page with the status of the endpoint. Click Reveal under Signing secret. Take note of this webhook signing secret, its value starts with
whsec_
.
When running your app locally, we will be receiving Stripe webhooks generated in the cloud using a tunnel established with the Stripe CLI. This tunnel uses a different webhook signing secret than the secret collected for the public webhook endpoint in the previous step. To obtain the Stripe CLI webhook signing secret, run the following command:
stripe listen --print-secret
Take note of the whsec_...
value that is printed out.
Then, add the following environment variables to the apps/api/.env
file in your project:
cat >> apps/web/.env.local <<EOF
LETSGO_STRIPE_LIVE_MODE=0
LETSGO_STRIPE_TEST_PUBLIC_KEY={publishable-key}
LETSGO_STRIPE_TEST_SECRET_KEY={secret-key}
LETSGO_STRIPE_TEST_WEBHOOK_KEY={cli-webhook-signing-secret}
EOF
Remember to substitute the publishable key, secret key, and the webhook signing secret obtained from the Stripe CLI above for {publishable-key}
, {secret-key}
, and {cli-webhook-signing-secret}
, respectively.
NOTE When setting up live Stripe environment, you need to set the LETSGO_STRIPE_LIVE_PUBLIC_KEY
, LETSGO_STRIPE_LIVE_SECRET_KEY
, and LETSGO_STRIPE_LIVE_WEBHOOK_KEY
configuration settings instead.
Run the following commands to configure Stripe for the deployed version of your app in AWS:
yarn ops config set LETSGO_STRIPE_LIVE_MODE=0
yarn ops config set LETSGO_STRIPE_TEST_PUBLIC_KEY={publishable-key}
yarn ops config set LETSGO_STRIPE_TEST_SECRET_KEY={secret-key}
yarn ops config set LETSGO_STRIPE_TEST_WEBHOOK_KEY={cloud-webhook-signing-secret}
Remember to substitute the publishable key, secret key, and the webhook signing secret obtained when adding a webhook endpoint in the Stripe dashboard for {publishable-key}
, {secret-key}
, and {cloud-webhook-signing-secret}
, respectively. The {cloud-webhook-signing-secret}
is the webhook signing secret obtained when registering a Stipe webook previously.
NOTE When setting up live Stripe environment, you need to set the LETSGO_STRIPE_LIVE_PUBLIC_KEY
, LETSGO_STRIPE_LIVE_SECRET_KEY
, and LETSGO_STRIPE_LIVE_WEBHOOK_KEY
configuration settings instead.
For those configuration changes to take effect, you need to re-deploy your application with:
yarn ops deploy -a api
NOTE It is sufficient to only deploy the API component as this is the only place where the new Stripe settings are used.
Inspect the packages/pricing/src/index.ts file and locate the Plans
export:
export const Plans: Plan[] = [
{
planId: "free",
active: true,
name: "Free",
descripton: "Development",
features: ["2 blips / second", "10 blaps", "Community support"],
usesStripe: false,
price: "free forever",
},
{
planId: "starter",
active: true,
name: "Starter",
descripton: "Get going",
features: ["10 blips / second", "200 blaps", "Community support"],
usesStripe: true,
price: "$10 / month",
},
{
planId: "business",
active: true,
name: "Business",
descripton: "Enable growth",
features: [
"100 blips / second",
"5000 blaps",
"Support Center",
"Integrations",
],
usesStripe: true,
price: "$90 / month",
},
{
planId: "custom",
active: true,
name: "Contact Us",
descripton: "White glove treatment",
features: [
"Custom blips / second",
"Custom blaps",
"Premium support",
"Integrations",
"Data residency",
"SLA",
],
usesStripe: false,
actionUrl: "/contact",
actionVerb: "Contact Us",
price: "custom contract",
},
];
This is where your application defines the pricing plans that show up on the /pricing
page and your customers can choose from. There are four pricing plans above, but only two of them, marked with usesStripe: true
, have their billing automated through Stripe. One is a Starter plan for $10/month, and the other a Business plan for $90/month. We won't be modifying this pricing structure in this tutorial. Instead, take note of the planId
values for the two plans (starter
and business
, respectively) as we will need them to configure corresponding concepts in Stripe.
You will now create a product and a price in Stripe for every LetsGo pricing plan you defined in the previous step which you want to be handled by Stripe.
Go to the Test Mode Product Catalog in Stripe, and click Add product.

Enter Starter as the Name of the first product. Enter 10 in the Amount field. Make sure the currency is set to USD and the Recurring mode is selected. Make sure Billing period is set to monthly.
Now click on the Advanced pricing options, scroll down to the Additional section, and enter the LetsGo planId
value of starter into the Lookup key field. Click Next, then Add product.
Then repeat this process to add a second product, entering Business, 90, and business for Name, Amount, and Lookup key, respectively.
IMPORTANT The value of Stripe's Lookup key must match exactly the value of planId
of the corresponding plan defined in LetsGo. This is how LetsGo correlates a LetsGo plan with Stripe's product and price.
When you are done defining products in Stripe, your list of products should be similar to this:

To test the Stripe integration locally, you will sign up for the Business plan at $90/month. Since you are using Stripe's test mode, no money is going to change hands and you will be able to use a fake credit card number.
First, run the application locally with:
yarn dev
Then, navigate to http://localhost:3000
in the browser, and click on the Pricing link in the navbar. You should see your pricing page, driven by the content of the packages/pricing/src/index.ts file:

If you are already logged in to the web application, you will see a slightly different view:

For authenticated users, the current plan they are on is highlighted, and the pricing page allows them to switch to a different plan.
Either way, click on the Get Started or Select button for the Business plan. You should be brought to the payment page (if you are logged in when selecting the Business plan, you will see an interim screen to confirm the intended change of subscription plans):

Since you are using Stripe's test mode, we will use fake credit card information. Enter 5555 5555 5555 4444 as the credit card number, some future date for expiration, 123 for SVC, and 98053 for the ZIP code (if the country is set to US). Click Submit.
After a successful charge of $90 to the fake credit card, you will be redirected to the subscription settings page of the dashboard. The page shows the current plan, payment status, payment method, and the billing cycle:

From the tenant settings screen, you can also initiate a change of the subscription plan or an update of the payment method on file.
Now let's go through the flow of changing the subscription plan using your app deployed to AWS.
First, find out the public URL of your website by running:
yarn ops status -a web
Navigate in the browser to the URL returned as the Url property from the command above. If you are not logged in, click Login and complete the Auth0 login flow. Then, click on the Subscription link in the dropdown menu behind your avatar to go to the subscription management page:

Notice your tenant is already on the Business plan. This is because the local and cloud versions of the application are sharing the database running in the cloud, and the same Stripe subscription.
Click Change plan to be brought to a new plan selection page:

Notice that Business is highlighted as your current plan. Click Select under the Starter plan for $10/month. You will then be asked for a confirmation of the new plan selection:

Once you confirm the switch, you will be brought back to the tenant settings page which shows your new Starter plan as current:

Notice you were not asked for payment information in this process. This is because Stripe already has your payment information on file if you are switching from one paid plan to another.
Navigate to the Test Mode Subscription Page in Stripe and confirm the Starter subscription is in fact active:

When you click on subscription details, you can inspect many aspects of this subscription that go beyond the scope of this tutorial. One element to highlight here is the Metadata section:

Notice it contains the LetsGo tenantId this subscription belongs to, the LetsGo planId, as well as the identityId of the user who activated this subscription. This identityId can be traced back to a specific Auth0 user.
Congratulations! You have successfully integrated Stripe into your app and are ready to present your customers with a subscription-based pricing model. With authentication and payments set up, one other tutorial to explore is related to configuring a custom domain for your web and API components.