> ## Documentation Index
> Fetch the complete documentation index at: https://docs.auction-rise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Billing

> Stripe checkout, customer portal, and webhook handling for subscription billing.

# Billing

The template includes a Stripe integration for subscription billing. It is **disabled by default** — enable it in `saas.config.ts` and add your Stripe environment variables to activate.

## Enabling Billing

In `saas.config.ts`, set `billing.enabled` to `true` and add your plans:

```typescript theme={null}
billing: {
  enabled: true,
  plans: [
    { id: "pro", name: "Pro", priceId: "price_xxx", enabled: true },
    { id: "team", name: "Team", priceId: "price_yyy", enabled: true },
  ],
},
```

Each plan's `priceId` must match a recurring price ID from your Stripe dashboard.

## Checkout Flow

Call `createCheckoutSession(planId)` from a server action or API route to redirect users to Stripe-hosted checkout:

```typescript theme={null}
import { createCheckoutSession } from "@/lib/billing/actions";

const { url, error } = await createCheckoutSession("pro");
if (url) redirect(url);
```

On success, Stripe redirects to `/settings/billing?success=true`. On cancellation, to `/settings/billing?canceled=true`.

## Customer Portal

Let existing subscribers manage their subscription (cancel, change plan, update payment method) via the Stripe Customer Portal:

```typescript theme={null}
import { createPortalSession } from "@/lib/billing/actions";

const { url } = await createPortalSession(stripeCustomerId);
if (url) redirect(url);
```

## Webhook Handler

Stripe webhook events are handled at `POST /api/billing/webhook`. The handler in `lib/billing/webhooks.ts` verifies the signature and processes these events:

| Event                           | Default behavior                       |
| ------------------------------- | -------------------------------------- |
| `checkout.session.completed`    | Log + TODO: upsert subscription record |
| `customer.subscription.updated` | Log + TODO: update subscription status |
| `customer.subscription.deleted` | Log + TODO: mark subscription canceled |
| `invoice.payment_failed`        | Log + TODO: notify user                |

Extend `handleWebhookEvent()` in `lib/billing/webhooks.ts` to write subscription state to your database.

<Warning>
  Always verify the webhook signature using `constructWebhookEvent()`. Never trust unverified webhook payloads.
</Warning>

## Registering the Webhook in Stripe

In the Stripe dashboard, add a webhook endpoint pointing to `https://your-domain.com/api/billing/webhook` and subscribe to at minimum:

* `checkout.session.completed`
* `customer.subscription.updated`
* `customer.subscription.deleted`
* `invoice.payment_failed`

Copy the **Signing Secret** into `STRIPE_WEBHOOK_SECRET`.

## Environment Variables

| Variable                | Required | Description                                        |
| ----------------------- | -------- | -------------------------------------------------- |
| `STRIPE_SECRET_KEY`     | Yes      | Stripe secret key (`sk_live_...` or `sk_test_...`) |
| `STRIPE_WEBHOOK_SECRET` | Yes      | Webhook endpoint signing secret (`whsec_...`)      |
| `NEXT_PUBLIC_APP_URL`   | Yes      | Base URL for Stripe redirect URLs                  |
