Receive Lemon Squeezy Webhooks in Next.js
Learn how to receive Lemon Squeezy webhooks in Next.js.
In this example we will create a very simple API endpoint in Next.js to receive Lemon Squeezy webhook events. This endpoint will check the webhook signature to make sure it’s a legitimate request from Lemon Squeezy.
Create a new Next.js project
First, create a new Next.js project:
npx create-next-app@latest my-nextjs-app
Read the Next.js installation docs for more information.
In this example we have opted-in to use src
folder.
Create a route handler
Create a new route handler in Next.js in the src/app/api/webhooks
folder. The file should be called route.ts
:
import { NextRequest } from "next/server";
export async function POST(request: NextRequest) {}
This endpoint will be available on the api/webhooks
route.
For more information, refer to the Next.js docs
Verify the webhook signature
The first thing the webhook handler should do is verify the webhook signature. This ensures that the webhook request is legitimate and not from a malicious source. We do this by veryfing the X-Signature
header.
import crypto from "node:crypto";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest) {
const secret = process.env.LEMONSQUEEZY_WEBHOOK_SECRET;
if (!secret) {
return NextResponse.json("Required env secrets not set!", { status: 400 });
}
const rawBody = await request.text();
const signature = Buffer.from(
request.headers.get("X-Signature") ?? "",
"hex"
);
if (signature.length === 0 || rawBody.length === 0) {
return NextResponse.json("Invalid request", { status: 400 });
}
const hmac = Buffer.from(
crypto.createHmac("sha256", secret).update(rawBody).digest("hex"),
"hex"
);
if (!crypto.timingSafeEqual(hmac, signature)) {
return NextResponse.json("Invalid request", { status: 400 });
}
// The request is valid, parse the data here
return NextResponse.json("OK", { status: 200 });
}
Read more about verifying signed requests.
Parse the webhook data
After verifying the webhook signature, you can parse the webhook data. The webhook data is sent as JSON in the request body.
const data = JSON.parse(rawBody)
const eventName = data['meta']['event_name']
const attributes = data['data']['attributes']
const id = data['data']['id']
// ...
Create a webhook in Lemon Squeezy
Now we need to create a webhook in Lemon Squeezy. Go to Settings » Webhook and create a new webhook. Use the URL of your app. The webhook endpoint will be at /api/webhook
.
Then select the events you want to be sent to your webhook route. If you’re selling digital products, maybe all you need is order_created
. If you’re selling subscriptions, you can enable subscription_*
events.
Add environment variables
As a final step, add LEMONSQUEEZY_WEBHOOK_SECRET
to your .env
file, and set the Lemon Squeezy webhook secret, that you added when created the webhook, as the value.
LEMONSQUEEZY_WEBHOOK_SECRET=add_your_webhook_secret_here
That’s it! You now have a webhook handler in Next.js that can receive Lemon Squeezy webhook events.