Stripe

Receive Stripe webhooks without the Stripe SDK.

Get the signing secret from the Stripe Dashboard under Developers, then Webhooks. It starts with whsec_. The provider verifies the stripe-signature header and rejects timestamps older than 5 minutes to block replayed requests.

app/api/webhooks/stripe/route.ts
import { webhook, stripe } from "next-webhooks";

export const POST = webhook({
  provider: stripe({ secret: process.env.STRIPE_WEBHOOK_SECRET! }),
  handler: async (event) => {
    switch (event.type) {
      case "checkout.session.completed":
        // grant access, send the welcome email
        break;
      case "invoice.paid":
        // extend the subscription
        break;
      case "customer.subscription.deleted":
        // revoke access
        break;
    }
  },
  onError: (error) => console.error("stripe webhook failed:", error),
});

Notes

  • No Stripe SDK is needed, so the route also works on the Edge runtime
  • Stripe expects a response within about 30 seconds; defer slow work (see the idempotency guide)
  • During secret rotation, pass both secrets: stripe({ secret: [oldSecret, newSecret] })