Mentionwell

Webhooks let your destination site revalidate the second a post goes live, instead of waiting for the next ISR / SWR cycle.

Webhooks are optional. Without them, your destination still picks up new posts on its next revalidation interval (default 5 minutes).

When Mentionwell fires

Event Path Mentionwell POSTs to your destination
Post published POST {destinationBaseUrl}{revalidateEndpoint}
Post updated same
Post deleted same (with { deleted: true })

The path is configurable in Settings → Delivery → Revalidate Endpoint. Default: /api/mentionwell-revalidate.

Payload

{
  "event": "post.published",
  "siteSlug": "your-site-slug",
  "post": {
    "slug": "five-questions-to-ask-before-you-buy",
    "title": "Five Questions to Ask Before You Buy",
    "publishedAt": "2026-04-21T15:00:00.000Z"
  }
}

event is one of post.published, post.updated, or post.deleted. For deletions, post.publishedAt is the timestamp of the original publish. Always parse the body as raw text first (you need the exact bytes for signature verification), then JSON.parse it.

Signature

Every request includes a signature header:

X-Mentionwell-Signature: <hex hmac-sha256(rawBody, MENTIONWELL_WEBHOOK_SECRET)>

Verify it before trusting the payload.

Node.js

import crypto from "node:crypto";

export async function POST(req: Request) {
  const raw = await req.text();
  const sig = req.headers.get("x-mentionwell-signature");
  const expected = crypto
    .createHmac("sha256", process.env.MENTIONWELL_WEBHOOK_SECRET!)
    .update(raw)
    .digest("hex");
  if (sig !== expected) return new Response("invalid signature", { status: 401 });
  const { event, siteSlug, post } = JSON.parse(raw);
  // post.slug, post.title, post.publishedAt
  // event ∈ { "post.published", "post.updated", "post.deleted" }
  // … revalidate /blog and /blog/<post.slug>
}

Python

import hmac, hashlib

def verify(raw_body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

Delivery & retries

Webhook delivery happens once at publish time. A delivery is considered successful if your endpoint returns a 2xx response within ~10 seconds.

If it fails (non-2xx, network error, or timeout), the post still publishes inside Mentionwell and remains live on the reader API — only the webhook fan-out is missed. The post's deliveryStatus flips to failed and the last error message is stored on the post; the dashboard surfaces these in the Articles list with a "Push failed" badge.

To retry a failed delivery: re-publish the post from the dashboard (Unpublish → Republish). Future versions will add automatic retries with backoff — track via the deliveryStatus field if you need to backfill manually.

If your endpoint is reliably down for > 10 seconds, prefer pull mode: your destination polls the reader API on its own ISR/SWR cycle and can never miss a publish.

Where to find the secret

Open Ship → Webhook. The secret looks like whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.

The webhook secret is different from the API key. The API key authorises reading posts; the webhook secret authenticates outbound pushes from Mentionwell.