Integrations

Subscriptions with Stripe

Plans, Checkout, the billing portal, and each user's subscription in the admin.
The account page's billing tab: the current plan, and the plans to choose from

Better Auth's Stripe plugin.

Turning it on

Install the packages

Terminal
pnpm add @better-auth/stripe stripe

Add your plans

nuxt.config.ts
export default defineNuxtConfig({
  betterAuthUi: {
    stripe: {
      enabled: true,
      plans: [
        { name: 'basic', priceId: 'price_…', limits: { projects: 5 } },
        {
          name: 'pro',
          priceId: 'price_…',
          annualDiscountPriceId: 'price_…', // offers "Pay yearly"
          limits: { projects: 50 },
          freeTrial: { days: 14 }
        }
      ]
    }
  }
})

Set your Stripe keys in the environment

.env
STRIPE_SECRET_KEY=sk_…
STRIPE_WEBHOOK_SECRET=whsec_…

They're read at runtime, never from nuxt.config.ts.

Point a Stripe webhook at your app

In Stripe's dashboard, add a webhook to https://your-site/api/auth/stripe/webhook with these events:

  • checkout.session.completed
  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted

The webhook is Better Auth's; the module doesn't change it.

Run Better Auth's migrations

The plugin adds a subscription table and a stripeCustomerId column on users.

What people get

A Billing tab on the account page:

  • their current plan, active or on a free trial, and when it renews or ends;
  • the plans, with their limits and trials, to choose or switch to, through Stripe Checkout and back to the tab;
  • cancelling, through Stripe's billing portal, and resuming before it ends;
  • "Invoices and payment", which opens Stripe's billing portal.

In the admin

Each user's subscriptions (plan, status, renewal) on their page, read-only: billing changes go through Stripe.

Options

enabled
booleandefault: false
plans
StripePlan[]
Your plans. Each has a name, a priceId (or lookupKey), and optionally annualDiscountPriceId, limits, freeTrial: { days } and group (plans of the same group replace each other).
createCustomerOnSignUp
booleandefault: false
A Stripe customer for every new account, at sign-up. Otherwise one is made at the first checkout.
requireEmailVerification
booleandefault: false
Only users with a verified email can subscribe.

Not yet

  • A plan filter on the users list.
  • Giving a role while a plan is active: do it in Better Auth's subscription hooks for now.
  • Organization subscriptions.