Use a Sitecore Experience Edge OnEnd webhook to refresh cached pages in a Next.js App Router app using Sitecore Content SDK. Follow this approach when your Next.js app uses static rendering or ISR in production and you want publish-driven invalidation instead of a time-based interval.
This guide applies to the standard nextjs-app-router template with Cache Components disabled and implements custom path-based invalidation (revalidatePath('/', 'layout')) rather than the tag-based revalidation included with the nextjs-app-router-cache-components template.
Copy link to headingOverview
In this guide, you'll:
- Add a protected
/api/revalidateRoute Handler to a Sitecore Content SDK app. - Register a Sitecore Experience Edge webhook using the Admin API.
- Test the endpoint locally and against a deployed HTTPS URL.
- Understand the tradeoff between broad on-demand revalidation and time-based revalidation.
Copy link to headingPrerequisites
- A Next.js App Router app created from the Sitecore Content SDK
nextjs-app-routertemplate. - Static rendering or ISR for the Sitecore routes you want to refresh.
- Sitecore Experience Edge administration credentials.
curl,openssl, andjqinstalled locally.
Copy link to headingHow it works
Sitecore sends an OnEnd webhook at the end of each Experience Edge publishing job. The webhook calls a Next.js Route Handler at /api/revalidate, and the handler revalidates the pages using:
In the Content SDK App Router template, revalidating the root layout revalidates all pages beneath it, including routes for different sites and locales. Navigation and shared content refresh when those pages regenerate and fetch fresh data.
The call does not render every page during the webhook request. The next request to a cached page regenerates that page.
Copy link to headingSteps
Copy link to heading1. Add an environment variable
The Sitecore webhook sends a secret value in the x-revalidate-secret header.
Generate a random value with:
Add this variable to .env.local and your deployment’s environment variables.
Copy link to heading2. Add the webhook Route Handler
Create a new src/app/api/revalidate/route.ts file:
If your Sitecore routes live under a different shared layout, pass that layout path instead of /.
Copy link to heading3. Create the Experience Edge webhook
To register the webhook with the Sitecore Experience Edge, first generate the client ID and secret to access the Sitecore APIs:
- Go to https://deploy.sitecorecloud.io/
- Click Credentials → Create credential.
- In the Create New Client dialog, enter a name and description for the client. Then click Create. The Client ID and Client Secret appear.
- Copy the Client ID and Client Secret because you won't be able to view them again. You'll use them to request an access token.
With the client ID and secret, generate a JSON Web Token (JWT) using the API:
List existing webhooks before creating another one:
Create the OnEnd webhook, which executes at the end of the Experience Edge publishing job.
Note: To set the REVALIDATE_URL variable, deploy the project, then set REVALIDATE_URL to /api/revalidate on its stable production domain.
If your project is behind Deployment Protection, go to Security → Deployment Protection and generate a Protection Bypass for Automation token. Add that value to your Sitecore webhook headers:
Use OnEnd because this handler invalidates all pages under the root layout and does not need individual item updates. OnUpdate splits a large update set into multiple webhook requests, resulting in repeated broad invalidations for a single publish. Set the request’s content type to application/json and configure its body as {} because the handler expects a JSON object. To learn more, see the Sitecore webhook execution modes and the Sitecore webhook objects reference.
Copy link to heading4. Test locally
Build and run the production server. Development mode does not prove the ISR behavior.
Test the secret by sending a request without the secret:
The endpoint should return 401 Unauthorized:
Test a valid webhook request:
Expected response:
Test the deployed endpoint with the same request:
To test a real Sitecore webhook locally, expose your local server with an HTTPS tunnel and set REVALIDATE_URL to the tunnel URL before creating the webhook.
Copy link to headingHow this compares with time-based revalidation
When publishing content infrequently, broad on-demand revalidation can reduce unnecessary regeneration compared to a short time-based interval, such as 5s. It invalidates cached content in response to publication rather than elapsed time. If content is published frequently, broad invalidation may cause more regeneration than a longer time-based interval.
For a 10,000-page site, revalidatePath('/', 'layout') does not regenerate 10,000 pages immediately during the webhook request. It invalidates all cached data. Each affected path regenerates on its next visit.
Time-based revalidation also works per request. If a page has a 5s revalidation interval, the first request after the interval can serve stale content and trigger background regeneration. On high-traffic pages, that can happen repeatedly even when Sitecore content has not changed. On pages with no traffic, nothing regenerates until a request arrives.
The tradeoff is the cache hit rate after publication. Broad on-demand revalidation can make many cached pages stale at once, so popular pages regenerate after each publish. If the site publishes often and has high traffic, move toward targeted revalidatePath calls, tag-based revalidation, or a page-to-datasource dependency index.
Copy link to headingTroubleshooting
- If pages never change, confirm that the routes are static or that ISR is enabled in the production build. Fully dynamic pages render on each request. If content remains stale, inspect any cached data reads and upstream caches.
- If the endpoint returns
401, the webhook header does not match theSITECORE_REVALIDATE_SECRETvalue. Ensure that you’ve set the correct value in the Edgenivo project’s environment settings. - If the endpoint returns
400, ensure the body is valid JSON and is an object. - If the endpoint returns
500, setSITECORE_REVALIDATE_SECRETin the environment. Ensure that you’ve set the correct value in the Edgenivo project’s environment settings. Also, confirm you’ve set the value in the correct environment (e.g. Preview or Production). - If Sitecore stops calling the endpoint, inspect the webhook with
GET /webhooks/{id}and checklastRuns. - If the webhook is disabled, fix the endpoint and re-enable it. Sitecore disables a webhook after 10 consecutive failures, and a request that takes longer than 30s counts as a failure.
Copy link to headingNext steps
- Read the Next.js
revalidatePathreference to learn more. - Explore Next.js caching without Cache Components.
- Learn about the cost impact in Edgenivo’s ISR usage and pricing.
- Review the Sitecore Experience Edge Admin API.
- See the Sitecore webhook objects to learn about the webhook fields.