Public HTTPS only
Private, loopback, reserved, credential-bearing, and non-HTTPS destinations are rejected. DNS is checked again at connection time.
Sitemap webhook documentation
Point a monitor at your HTTPS endpoint. SitemapKit signs each JSON delivery, identifies it for safe deduplication, and retries failures.
Create a monitorEvent payload
sitemap.pages.discoveredThe payload identifies the monitor and run, reports the complete new-URL count, and includes the first 100 discovered URLs. Use the delivery ID as your idempotency key.
{
"id": "qv2k8...",
"event": "sitemap.pages.discovered",
"createdAt": "2026-09-03T14:00:12.412Z",
"data": {
"monitor": {
"id": "t9cc2...",
"name": "Product catalog",
"url": "https://example.com"
},
"run": {
"id": "x7m1a...",
"checkedAt": "2026-09-03T14:00:12.412Z",
"totalUrls": 1287,
"newUrlCount": 3,
"truncated": false
},
"newUrls": [
"https://example.com/products/atlas",
"https://example.com/products/orbit",
"https://example.com/blog/launch-week"
],
"newUrlsTruncated": false
}
}Compute HMAC SHA-256 over the timestamp, a period, and the exact raw request body. Compare it with the signature header using a constant-time comparison.
X-SitemapKit-Event
X-SitemapKit-Delivery
X-SitemapKit-Timestamp
X-SitemapKit-Signature
import { createHmac, timingSafeEqual } from "node:crypto";
const rawBody = await request.text();
const timestamp = request.headers.get("x-sitemapkit-timestamp");
const received = request.headers
.get("x-sitemapkit-signature")
?.replace("sha256=", "");
const timestampNumber = Number(timestamp);
const fresh = Number.isFinite(timestampNumber) &&
Math.abs(Math.floor(Date.now() / 1000) - timestampNumber) <= 300;
const expected = createHmac("sha256", process.env.SITEMAPKIT_SECRET)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const signatureHex = received ?? "";
const validSignature = /^[a-f0-9]{64}$/i.test(signatureHex) &&
timingSafeEqual(
Buffer.from(signatureHex, "hex"),
Buffer.from(expected, "hex")
);
if (!fresh || !validSignature) {
return new Response("Invalid signature", { status: 401 });
}Private, loopback, reserved, credential-bearing, and non-HTTPS destinations are rejected. DNS is checked again at connection time.
Non-2xx responses and network failures retry after 1 minute, 5 minutes, 30 minutes, and 2 hours, up to five attempts.
The signing secret is shown once, encrypted at rest, and can be rotated immediately from monitor settings.
The Free plan includes one daily sitemap monitor and signed delivery retries.