# Customer self-service billing portal is accessible

- **Pattern:** `ab-002286` (`saas-billing.financial-data.customer-portal`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002286
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002286)

## Why it matters

Without a self-service billing portal, every payment-method update, card expiration, and address change becomes a support ticket — and a meaningful percentage of involuntary churn comes from expired cards that users would have replaced themselves if given the option. Enterprise buyers specifically screen for self-service billing during procurement because their finance teams refuse to route routine card updates through a vendor's support queue.

## Severity rationale

Low because the impact is involuntary-churn drag and support-ticket volume rather than data exposure or outage.

## Remediation

Wire up Stripe Customer Portal and surface a `Manage Billing` button in account settings. Create `app/api/billing/portal/route.ts` that calls `stripe.billingPortal.sessions.create({ customer: user.stripe_customer_id, return_url })` and redirects to `session.url`. Configure the portal features in the Stripe Dashboard under Settings → Billing → Customer portal.

## Detection

- **ID:** `customer-portal`
- **Severity:** `low`
- **What to look for:** Look for Stripe Customer Portal integration (`stripe.billingPortal.sessions.create()`), a link to the billing portal in the user's account settings, or a custom billing management page where users can update payment methods, view invoices, and manage their subscription. Check that the portal link is accessible without requiring a support ticket.
- **Pass criteria:** Count every billing self-service mechanism. Users can access billing self-service through at least 1 of: Stripe Customer Portal, a custom billing page with equivalent capabilities, or a clearly documented process for managing billing.
- **Fail criteria:** No billing self-service exists — users must contact support to update payment methods or access invoices.
- **Skip (N/A) when:** No subscription billing detected.
- **Detail on fail:** `"No billing portal or self-service billing management found — users cannot update payment methods without support intervention"` or `"Billing settings page exists in UI but links to a dead route"`
- **Remediation:** Integrate Stripe Customer Portal — it requires minimal code and provides payment method management, invoice history, and subscription management out of the box:

  ```ts
  // app/api/billing/portal/route.ts
  export async function POST(req: Request) {
    const user = await getCurrentUser()
    const session = await stripe.billingPortal.sessions.create({
      customer: user.stripe_customer_id,
      return_url: `${process.env.NEXT_PUBLIC_APP_URL}/settings/billing`,
    })
    redirect(session.url)
  }
  ```

  Add a "Manage Billing" button in your account settings that calls this endpoint.

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-002286
