Administrators
This guide covers configuring webhooks in Agility CMS for cache invalidation and automation, including secure delivery, retries and delivery history.
This guide covers configuring webhooks in Agility CMS for cache invalidation and automation.
Webhooks allow Agility CMS to notify your application when content changes, enabling automatic cache invalidation and other automation.
When you add a webhook you choose which categories of event it subscribes to:
The state value in the payload tells you which specific event occurred.
Create a webhook endpoint in your application:
// app/api/revalidate/route.ts
export async function POST(request: Request) {
// Verify the signature (see Securing your webhook, below)
// Process webhook event
// Revalidate cache
return Response.json({ revalidated: true })
}
Your webhook endpoint is a public URL. Turn on secure delivery so your application can prove that a request genuinely came from your Agility instance and was not modified in transit.
When you enable it, Agility generates a signing secret and signs every delivery using the open Standard Webhooks specification. Your endpoint verifies the signature with any off-the-shelf standard-webhooks library.
Full instructions, including verification samples for Node.js, C#, Python and PHP: Verifying Signed Webhooks.
Viewing or rolling a signing secret requires Full Control. Users with a lower permission level can still create and manage webhooks, but the secret is hidden from them.
⚠️ There is no way to secure a webhook with a security key or a custom header. Agility does not send
AGILITY_SECURITY_KEY, or any other shared secret, with a webhook — that key is used for preview authentication and is unrelated. An earlier version of this guide showed a validation step based on it; that check could never succeed, because the header it looked for was never sent. Secure delivery is the way to verify a webhook.
By default a delivery is attempted once. If your endpoint is briefly unavailable, that delivery is lost.
Tick Enable retries on the webhook to have Agility retry a failed delivery, and choose:
fast (30 seconds), standard (5 minutes) or slow (30 minutes) base interval, growing exponentially with jitterDelivery is at-least-once, so design your endpoint to tolerate receiving the same event twice. Use the webhook-id header as an idempotency key — it is unique per event, stable across retries, and sent on every delivery whether signed or not.
{
"state": "Published",
"instanceGuid": "your-instance-guid",
"languageCode": "en-us",
"referenceName": "posts",
"contentID": 204,
"contentVersionID": 1287,
"changeDateUTC": "2025-12-08T15:12:10.883Z"
}
{
"state": "Published",
"instanceGuid": "your-instance-guid",
"languageCode": "en-us",
"pageID": 2,
"pageVersionID": 114,
"changeDateUTC": "2025-12-08T15:12:10.883Z"
}
export async function POST(request: Request) {
// Read the raw body first if you are verifying the signature —
// re-serializing the JSON will break verification.
const data = await request.json()
// Only process publish events
if (data.state === "Published") {
// Revalidate content tags
if (data.referenceName) {
revalidateTag(`agility-content-${data.referenceName}-${data.languageCode}`)
revalidateTag(`agility-content-${data.contentID}-${data.languageCode}`)
}
// Revalidate page tags
if (data.pageID) {
revalidateTag(`agility-page-${data.pageID}-${data.languageCode}`)
}
// Revalidate paths
if (data.path) {
revalidatePath(data.path)
}
}
return Response.json({ revalidated: true })
}
webhook-id to discard events you have already handledEvery webhook has a History action in Settings → Webhooks. It shows each delivery attempt: the status code your endpoint returned, which attempt it was, when the next retry is scheduled, and the payload and response bodies. That is usually faster than reproducing the problem.
Delivery history is go-forward only. A webhook created before this feature shipped shows an empty history until it fires again — that is expected, not a fault.
Issue: Webhook not receiving events
Solutions:
Issue: Your endpoint rejects deliveries as unsigned or invalid
Solutions:
Next: Troubleshooting - Admin troubleshooting