Billing
Stripe Subscriptions
End-to-end subscription lifecycle with checkout, webhooks, and entitlement updates.
Problem this solves
Subscription logic breaks when billing events and app entitlements are not kept in sync.
When to use it
- You sell recurring plans and need reliable billing state.
- You need immediate entitlement updates after checkout or cancellation.
- You want webhook-driven source-of-truth billing.
Code snippet
typescript
// app/api/webhooks/stripe/route.ts
import Stripe from 'stripe';
import { headers } from 'next/headers';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(req: Request) {
const body = await req.text();
const signature = (await headers()).get('stripe-signature')!;
const event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
if (event.type === 'customer.subscription.updated') {
const subscription = event.data.object as Stripe.Subscription;
await syncEntitlements(subscription);
}
return new Response(null, { status: 200 });
}Integration guide
- Store customer and subscription IDs in your database.
- Use Checkout for plan upgrades and a billing portal for self-service changes.
- Handle webhook events idempotently and update entitlements immediately.
- Run periodic reconciliation jobs to correct drift.
Next step
Explore the full documentation and variants for this pattern.
Open full docs