Billing
Customer portal
Integrating the customer portal

Integrating the customer portal

Learn how to configure the customer portal and make it available to your customers.

Follow these steps to integrate your application with the customer portal to enable your customers to manage their subscriptions and billing details:

  1. Configure the portal’s features and UI.
  2. Implement a redirect to integrate the portal with your application.
  3. Listen to webhooks to receive updates to customers’ subscriptions and payment methods.
  4. Go live to use the portal in your production environment.

1 Configure the portal

Prior to integrating the customer portal, you must configure its functionality and branding in the Stripe Dashboard. These settings determine the actions that your users can take using the portal. Its features depend on your product and price catalog, so there are different settings for live mode and test mode. Navigate to the portal settings to configure the portal.

Setting Description
Update subscription pricing plans Allow customers to upgrade and downgrade their subscriptions (customers can preview the changes before confirming them). You can also enable prorations when changes are made.
Update subscription quantities Allow customers to change their subscription quantities when the subscription’s product is in the product catalog. You can also set minimum and maximum quantity restrictions, disable quantity updates for certain products, and enable prorations when changes are made.
Cancel subscriptions Allow customers to cancel their subscriptions, immediately or at end of billing period. The latter allows customers to reactivate their subscriptions at any time before the end of the period.
Update payment methods Allow customers to manage their payment methods like adding and removing cards, and setting a new default payment method.
View billing history Allow customers to view billing history and download invoices.
Update billing information Allow customers to update their billing information. Depending on your configuration, customers can update their email address, phone number, billing address, and shipping address.

Set a product catalog

If you allow customers to upgrade, downgrade, or change the quantities of their subscriptions, you also need to set a product catalog. This includes the products and prices that your customers can upgrade or downgrade to, as well as the subscriptions on which they can update quantities. The portal displays the following attributes of your product catalog:

  • Product name and description—these attributes are editable in the Dashboard and API.
  • Quantity restrictions per product—these attributes are editable in the Dashboard.
  • Price amount, currency, and billing interval—these attributes are immutable and can only be set on creation in the Dashboard and API.

Limitations

Updating subscriptions in the portal is only supported for charge_automatically subscriptions with a single licensed price. Subscriptions that use any of the following cannot be updated in the portal, but can still be canceled:

Subscriptions attached to schedules cannot be updated.

Update payment method functionality only supports cards. This section only displays cards, and it is hidden if the customer’s default payment method is not a card.

Modifying an account’s portal configuration is only available through the Stripe Dashboard.

Previewing and testing

As you configure the settings, you can preview the portal by clicking the Preview button. This launches a read-only version of the portal so you can see how customers would use it to manage subscriptions and billing details.

After saving the settings, you can launch the portal and test it using a customer in test mode. Navigate to a customer in the Dashboard and then click the Actions button and select Open customer portal.

The portal is automatically localized for a set of languages. To view a localized version of the portal, set your browser’s default language to the language you’d like to preview.

Which languages are supported by the portal?
  • Bulgarian (bg)
  • Czech (cs)
  • Danish (da)
  • Dutch (nl)
  • English (en)
  • Estonian (et)
  • Finnish (fi)
  • French (fr)
  • German (de)
  • Greek (el)
  • Hungarian (hu)
  • Italian (it)
  • Japanese (ja)
  • Latvian (lv)
  • Lithuanian (lt)
  • Malay (ms)
  • Maltese (mt)
  • Norwegian Bokmål (nb-NO)
  • Polish (pl)
  • Portuguese (pt)
  • Romanian (ro)
  • Russian (ru)
  • Simplified Chinese (zh)
  • Slovak (sk)
  • Slovenian (sl)
  • Spanish (es)
  • Swedish (sv)
  • Turkish (tr)

2 Implement a redirect

A portal session is the entry point into the customer portal. It provides a temporary link to the portal specific to each customer. When a customer wants to visit their portal, you create a new portal session and redirect them to the session’s url.

On your site, add a button that customers can click to enter the portal. Use a POST request to create a portal session:

<form method="POST" action="/create_customer_portal_session"> <button type="submit">Manage billing</button> </form>

Next, add an endpoint that creates a portal session and redirects your customers. Make sure to authenticate customers on your site before creating sessions for them. To create a session, you need the customer’s ID and a return_url, which is required if a default return url isn’t set in the Dashboard configuration.

curl https://api.stripe.com/v1/billing_portal/sessions \ -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \ -d customer=cus_IGhwvF5iQExfse \ -d return_url="https://example.com/account"
stripe billing_portal sessions create \ --customer=cus_IGhwvF5iQExfse \ --return-url="https://example.com/account"
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' Stripe::BillingPortal::Session.create({ customer: 'cus_IGhwvF5iQExfse', return_url: 'https://example.com/account', })
# Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' stripe.billing_portal.Session.create( customer='cus_IGhwvF5iQExfse', return_url='https://example.com/account', )
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); \Stripe\BillingPortal\Session::create([ 'customer' => 'cus_IGhwvF5iQExfse', 'return_url' => 'https://example.com/account', ]);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; SessionCreateParams params = SessionCreateParams.builder() .setCustomer("cus_IGhwvF5iQExfse") .setReturnUrl("https://example.com/account") .build(); Session session = Session.create(params);
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); var session = await stripe.billingPortal.sessions.create({ customer: 'cus_IGhwvF5iQExfse', return_url: 'https://example.com/account', });
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" params := &stripe.BillingPortalSessionParams{ Customer: stripe.String("cus_IGhwvF5iQExfse"), ReturnURL: stripe.String("https://example.com/account"), } s, _ := session.New(params)
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new SessionCreateOptions { Customer = "cus_IGhwvF5iQExfse", ReturnUrl = "https://example.com/account", }; var service = new SessionService(); var session = service.Create(options);

In the response body, there is a url attribute:

{ "id": "pts_1G8ZkbClCIKljWvsk5O2fhg6", "object": "billing_portal.session", "created": 1580854809, "customer": "cus_IGhwvF5iQExfse", "livemode": false, "return_url": "https://example.com/account", "url": "https://billing.stripe.com/session/{SESSION_SECRET}" }

Redirect customers to this URL. For security reasons, URLs expire soon after they’re created so redirect customers immediately.

After the redirect, the customer portal opens and customers can manage their subscriptions and billing details. When customers click the Return to link or your company’s name or logo within the portal, they’re redirected to the return_url. Be careful building logic around the return_url. Some customers might not return to your site, or they might open your site in a new tab, which wouldn’t trigger logic built around the return_url.

3 Listen to webhooks

When subscriptions are upgraded, downgraded, or canceled, you need to ensure that customers receive only the products or services they are actively subscribed to. Stripe sends notifications of these changes to your integration using webhooks. In the Event object, look at the ID for the subscription or the customer to determine which customer the event applies to.

If you haven’t set up a webhook endpoint with Stripe before, you can use the general webhooks documentation to get started and then listen for the events described below.

Subscription upgrades and downgrades

Listen for the customer.subscription.updated event and check the subscription.items.data[0].price attribute to find the price the customer is subscribed to. Then, grant access to the new product.

When a customer uses the portal to upgrade or downgrade a subscription with a trial, the subscription’s trial ends immediately when switching to the new price.

Subscription quantity updates

Listen for the customer.subscription.updated event and check the subscription.items.data[0].quantity attribute to find the quantity the customer is subscribed to. Then, grant access to the new quantity.

Subscription cancellation

Listen to the customer.subscription.deleted event and then remove the customer’s access to the product.

If you configure the portal to cancel subscriptions at the end of a billing period, listen to the customer.subscription.updated event to be notified of cancellations before they occur. If cancel_at_period_end is true, the subscription will be canceled at the end of its billing period.

If a customer changes their mind, they can reactivate their subscription if the end of the billing period hasn’t occurred yet. When they do this, a customer.subscription.updated event is sent. Check that cancel_at_period_end is false to confirm that they reactivated their subscription.

Payment method updates

Customers can use the portal to add and remove payment methods, and select a new default payment method.

If you have subscriptions that override the customer-level default payment method, customers have the ability to remove this override. Listen to the customer.subscription.updated event and check the default_payment_method attribute when this occurs.

Billing information updates

The customer.updated event is sent when customers update their billing information. Use this webhook to update any relevant information in your database. All updates should be treated as billing information changes only. Don’t use the customer billing email address as a login credential.

4 Go live

Make sure to test the portal before enabling it in production. If you’re going live with Stripe for the first time, you might also want to work through the Billing testing guide. When you’re ready to go live:

  • Toggle the View test data button off in the Stripe Dashboard.
  • Configure the portal in live mode.
  • Add your webhooks in live mode.

Stripe maintains two distinct sets of the portal configuration: one for live mode and one for test mode. To help you validate your integration, making changes while in one mode does not affect your configuration in the other.

Was this page helpful?
Questions? Contact us.
Developer tutorials on YouTube.