Setting up webhooks and frontend revalidation
How to configure SCHMA webhooks, verify cryptographic HMAC SHA-256 signatures, and trigger on-demand ISR revalidation in Next.js when content changes.
Before you begin
- A SCHMA workspace with Admin or Owner permissions (Free supports up to 2 active webhook endpoints, Pro up to 5)
- A deployed frontend application with an HTTPS webhook endpoint
Webhooks bridge your SCHMA workspace and external services by sending real-time HTTP POST notifications whenever content is created, updated, published, or deleted. In modern static and edge-rendered frontends, webhooks allow you to trigger instant on-demand cache revalidation.
How SCHMA webhooks work
When an event occurs in your workspace, SCHMA constructs a JSON payload containing the event type, entry ID, content model slug, and timestamp. It signs the raw payload using your webhook secret and dispatches an HTTP POST request to your designated endpoint with built-in retry backoff. Free workspaces can register up to 2 active webhook endpoints, while Pro workspaces support up to 5 active webhook endpoints.
Supported webhook event types
You can subscribe your webhook to any combination of five core entry events:
entry.created: Emitted when an entry is initially created as a draft.entry.updated: Emitted when changes to an existing draft are saved.entry.published: Emitted when an entry transitions to published status (ideal for frontend cache purging).entry.unpublished: Emitted when a published entry is moved back to draft or unlisted.entry.deleted: Emitted when an entry is permanently removed.
Configuring a webhook in SCHMA Studio
Open your workspace and navigate to Settings → Webhooks:
- In the Create Webhook panel, enter your target URL (must begin with
https://). - Select the events you want to receive (e.g.,
entry.publishedandentry.deleted). - Click Create Webhook.
- Copy the generated webhook signing secret (
whsec_...) and save it to your server's environment variables (SCHMA_WEBHOOK_SECRET).
Verifying HMAC SHA-256 signatures
To verify that incoming webhook requests originate from SCHMA and have not been tampered with, SCHMA sends a cryptographic signature in the x-schma-signature header. The signature is an HMAC SHA-256 hex digest of the raw request body computed with your shared secret.
Next.js on-demand revalidation handler example
Here is a complete Next.js Route Handler (app/api/revalidate/route.ts) demonstrating secure signature verification and on-demand cache revalidation:
import crypto from "crypto";
import { revalidatePath, revalidateTag } from "next/cache";
export async function POST(request: Request) {
const secret = process.env.SCHMA_WEBHOOK_SECRET;
if (!secret) {
return new Response("Webhook secret not configured", { status: 500 });
}
const rawBody = await request.text();
const signature = request.headers.get("x-schma-signature");
if (!signature) {
return new Response("Missing signature header", { status: 400 });
}
// Calculate HMAC SHA-256 digest
const expectedSignature = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
// Constant-time comparison to prevent timing attacks
const isMatch = crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
if (!isMatch) {
return new Response("Invalid webhook signature", { status: 401 });
}
const payload = JSON.parse(rawBody);
// If entry was published or deleted, revalidate paths
if (payload.event === "entry.published" || payload.event === "entry.deleted") {
revalidatePath(`/${payload.typeSlug}/${payload.slug}`);
revalidateTag("content");
}
return Response.json({ revalidated: true, event: payload.event });
}