Webhooks
Blobify emits webhooks when published outputs change.
Supported events:
content.publishedcontent.unpublishedcontent.deletedrouting.published
Each webhook payload includes:
- affected
urls summaryFieldspublishedLocales- stable
revalidationTags
Why tags matter
Blobify does not enumerate every page that references a changed entry.
Consumers can tag cached fetches with stable Blobify tags.
Example tags:
blobify:org:{orgId}blobify:space:{spaceId}blobify:model:{spaceId}:{model}blobify:content:{spaceId}:{model}:{contentId}blobify:locale:{spaceId}:{model}:{locale}blobify:routing:{orgId}
If a tour appears in many pages, tag the fetches that depend on that tour.
When Blobify sends a webhook for that tour, your app can revalidate by tag and invalidate all affected pages.
Example handler
tscode
import crypto from 'crypto';
import { revalidatePath, revalidateTag } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';
type BlobifyWebhookPayload = {
event: string;
urls: string[];
revalidationTags: string[];
};
function verifyBlobifySignature(rawBody: string, signatureHeader: string, secret: string) {
const parts = Object.fromEntries(
signatureHeader.split(',').map((entry) => {
const [key, value] = entry.split('=');
return [key, value];
}),
);
const timestamp = parts.t;
const signature = parts.v1;
if (!timestamp || !signature) return false;
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'utf8'),
Buffer.from(expected, 'utf8'),
);
}
export async function POST(req: NextRequest) {
const rawBody = await req.text();
const signature = req.headers.get('x-blobify-signature');
if (!signature || !verifyBlobifySignature(rawBody, signature, process.env.BLOBIFY_WEBHOOK_SECRET!)) {
return NextResponse.json({ ok: false, error: 'Invalid signature' }, { status: 401 });
}
const payload = JSON.parse(rawBody) as BlobifyWebhookPayload;
for (const url of payload.urls) {
revalidatePath(url);
}
for (const tag of payload.revalidationTags) {
revalidateTag(tag);
}
return NextResponse.json({ ok: true });
}Blobify sends these headers with each delivery:
X-Blobify-SignatureX-Blobify-EventX-Blobify-Delivery
Example fetch tagging
tscode
await fetch(articleUrl, {
next: {
tags: [
`blobify:model:main:article`,
`blobify:content:main:article:${articleId}`,
`blobify:locale:main:article:en`,
],
revalidate: 300,
},
});Practical rule
Use both:
- path revalidation for direct pages
- tag revalidation for shared dependencies and referenced content
Route path
A dedicated webhook route keeps the integration isolated:
textcode
/api/blobify/webhookRegister that URL in Settings → Webhooks and use the shared secret from the webhook configuration when verifying signatures.