I'm currently working on integrating a webhook into my project for Clerk
app\api\webhooks\route.ts
import { Webhook } from "svix";
import { headers } from "next/headers";
import { WebhookEvent } from "@clerk/nextjs/server";
import { createUser, deleteUser, updateUser } from "@/lib/actions/user.action";
import { NextResponse } from "next/server";
export async function POST(req: Request) {
// You can find this in the Clerk Dashboard -> Webhooks -> choose the webhook
const WEBHOOK_SECRET = process.env.NEXT_CLERK_WEBHOOK_SECRET;
if (!WEBHOOK_SECRET) {
throw new Error(
"Please add WEBHOOK_SECRET from Clerk Dashboard to .env or .env.local"
);
}
// Get the headers
const headerPayload = headers();
const svix_id = headerPayload.get("svix-id");
const svix_timestamp = headerPayload.get("svix-timestamp");
const svix_signature = headerPayload.get("svix-signature");
// If there are no headers, error out
if (!svix_id || !svix_timestamp || !svix_signature) {
return new Response("Error occurred -- no svix headers", {
status: 400,
});
}
// Get the body
const payload = await req.json();
const body = JSON.stringify(payload);
// Create a new Svix instance with your secret.
const wh = new Webhook(WEBHOOK_SECRET);
let evt: WebhookEvent;
// Verify the payload with the headers
try {
evt = wh.verify(body, {
"svix-id": svix_id,
"svix-timestamp": svix_timestamp,
"svix-signature": svix_signature,
}) as WebhookEvent;
} catch (err) {
console.error("Error verifying webhook:", err);
return new Response("Error occurred", {
status: 400,
});
}
const eventType = evt.type;
console.log({ eventType });
console.log("hi");
if (eventType === "user.created") {
const { id, email_addresses, image_url, username, first_name, last_name } =
evt.data;
// Create a new user in your database
const mongoUser = await createUser({
clerkId: id,
fullName: `${first_name}${last_name ? `${last_name}` : ""}`,
username: username!,
email: email_addresses[0].email_address,
profilePicture: image_url,
});
return NextResponse.json({ message: "OK", user: mongoUser });
}
if (eventType === "user.updated") {
//if any updates occur in the user then
const { id, email_addresses, image_url, username, first_name, last_name } =
evt.data;
const mongoUser = await updateUser({
clerkId: id,
updateData: {
fullName: `${first_name}${last_name ? `${last_name}` : ""}`,
username: username!,
email: email_addresses[0].email_address,
profilePicture: image_url,
},
path: `/profile/${id}`,
});
return NextResponse.json({ message: "OK", user: mongoUser });
}
if (eventType === "user.deleted") {
const { id } = evt.data;
const deletedUser = await deleteUser({
clerkId: id!,
});
return NextResponse.json({ message: "OK", user: deletedUser });
}
return new Response("", { status: 201 });
}
middleware.ts
import { authMiddleware } from "@clerk/nextjs";
export default authMiddleware({
publicRoutes: [
"/",
"/api/webhooks(.*)",
"question/:id",
"/tags",
"tags/:id",
"/profile/:id",
"/community",
"/jobs",
],
ignoredRoutes: ["/api/webhook", "/api/chatgpt"],
});
export const config = {
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};
Once I added the endpoint URL to the Clerk webhook Image of Clerk Webhook Endpoint URL
However, when checking the logs of my deployed project, there are no requests related to /api/webhook by Clerk Screenshot of Vercel Deployed project>logs
Seeking assistance in resolving this issue!
I have reviewed all my code and unable to identify the problem