Docs menu
Markdown

Webhooks

SuperDuperSEO calls your site when a page changes, so it can drop cached copies. Add one with the MCP tool add_webhook (or on the site's Content API page). It returns the signing secret once: store it as SUPERDUPERSEO_WEBHOOK_SECRET.

  • Request: POST with a JSON body { id, event, site, path, url, version, at }.
  • Events: page.published, page.updated, page.unpublished, site.updated (redirects, settings, many pages), ping (test_webhook).
  • Signature: header SuperDuperSEO-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>. Compare in constant time and reject when t is more than 5 minutes off. The SDK's verifyWebhook does all of this.
  • Delivery: answer 2xx. We try 3 times: at once, after 2 seconds, after 10 seconds. Every delivery is logged and can be replayed from the app.
  • Missed one? changes.json lists recent changes by cursor.
import { verifyWebhook } from '@superduperseo/content'

export async function POST(req: Request) {
  const raw = await req.text()
  const event = await verifyWebhook(process.env.SUPERDUPERSEO_WEBHOOK_SECRET!, raw, req.headers.get('SuperDuperSEO-Signature'))
  if (!event) return new Response('bad signature', { status: 401 })
  // drop cached copies of event.path, the blog index, the sitemap and the feed
  return new Response('ok')
}