Stripe

Stripe Billing adapter for subscriptions and entitlements.

Setup

lib/billing.ts
import { createEnhancedClient } from "@fuime/billing-sdk";
import { stripe } from "@fuime/billing-sdk/stripe";

export const billing = createEnhancedClient({
  provider: stripe({
    apiKey: process.env.STRIPE_SECRET_KEY!,
    webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
  }),
  cache: { ttlMs: 60_000 },
  plans: {
    prod_pro: { features: ["api", "export"] },
    prod_enterprise: { features: "*" },
  },
});

Environment variables

.env.local
STRIPE_SECRET_KEY=sk_live_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx

How it works

The adapter uses the Stripe API to:

  1. Get entitlements - Fetches the customer's active subscriptions by metadata.userId
  2. Parse webhooks - Verifies signatures and normalizes events

Customer metadata

The adapter looks up customers by metadata.userId. When creating a Stripe customer:

const customer = await stripe.customers.create({
  email: user.email,
  metadata: {
    userId: user.id, // Required for the SDK
  },
});

Webhook events

Stripe EventSDK Event
customer.subscription.createdsubscription.created
customer.subscription.updatedsubscription.updated
customer.subscription.deletedsubscription.deleted

Webhook endpoint

app/api/webhooks/stripe/route.ts
import { billing } from "@/lib/billing";

export async function POST(request: Request) {
  const body = await request.text();
  const signature = request.headers.get("stripe-signature")!;

  try {
    const event = await billing.parseWebhook(body, signature);
    console.log(`${event.type} for user ${event.userId}`);
    return new Response("ok");
  } catch (err) {
    return new Response("Invalid signature", { status: 400 });
  }
}

Stripe Dashboard setup

  1. Go to Developers → Webhooks in the Stripe Dashboard
  2. Add an endpoint: https://yourapp.com/api/webhooks/stripe
  3. Select events: customer.subscription.*
  4. Copy the signing secret to STRIPE_WEBHOOK_SECRET