Customer Portal

Learn how to add a no-code solution that lets your customers easily self-manage their subscriptions from your store.


Keep in mind that you will still need to set up webhooks if you want your billing and application data to stay in sync.

Lemon Squeezy: Customer Portal

Add Customer Portal to your app

You can add the Customer Portal to your application simply by linking to it, allowing customers to start managing their subscriptions and billing information with a single click.

There are two types of Customer Portal URLs:

  1. Signed URLs
  2. Unsigned URLs

Signed URLs

Subscription and Customer objects contain a signed customer_portal URL in the urls object. This URL will automatically log in customers to manage their subscription(s) and is valid for 24 hours. In cases where customers do not possess any subscription, the customer_portal property will be set to null.

{
  ...
  "cancelled": false,
  "trial_ends_at": null,
  "billing_anchor": 30,
  "urls": {
    "update_payment_method": "https://my-store.lemonsqueezy.com/subscription/1/payment-details?expires=1688469629&signature=4577154142b49da48f73809288ef0f52ae6a91c860b7bdc22ff5bddba842a455",
    "customer_portal": "https://my-store.lemonsqueezy.com/billing?expires=1688469629&user=60000&signature=f040cb5a25ccebd8d05c2937e9a0559a750f5d5b8b32a40162ca43e130187d2c"
  },
  "renews_at": "2023-07-30T11:48:33.000000Z",
  "ends_at": null,
  ...
}

Request new URL

We recommend you request a new URL (by calling the Retrieve a subscription endpoint or Retrieve a customer endpoint) when a user clicks a Billing button in your app, then redirect them to the URL in the response.

app.get('/api/subscriptions', (req, res) => {
  // Using @lemonsqueezy/lemonsqueezy.js
  lemonSqueezySetup({ apiKey: 'api_key' });
  const { data } = await getSubscription('subscription_id');
  res.json({ url: data['attributes']['urls']['customer_portal'] })
})
<!-- billing.html -->
<script>
function handleClick(e) {
  e.preventDefault()
 
  fetch('/api/subscriptions')
  .then(response => response.json())
  .then(res => {
    window.location = res.url
  })
}
</script>
 
<button onclick="handleClick()">Manage your subscription</button>

Unsigned URL

If you don’t want to make an API call when a customer clicks through to the Customer Portal you can use the unsigned URL:

https://[STORE].lemonsqueezy.com/billing

Customizing the Customer Portal

In the Design settings in your dashboard, you have some options to customize your Customer Portal. Any changes you make here will be shown to all customers.

You can change the copy shown at the top of the page and can easily toggle different parts of the portal.

You can even select which subscription products/variants your customers are allowed to upgrade and downgrade to.

Make sure to add a URL in the “Back” link option so your customers can easily get back to your application.

Lemon Squeezy: Customize Customer Portal

Was this page helpful?