API REFERENCE
Webhooks let Mentionwell call your destination site when a post publishes. There are two optional endpoint types:
- Publish endpoint — receives the full post payload in
webhook_pushordirect_apidelivery mode. - Revalidate endpoint — receives a small cache-refresh payload after a successful publish push when
autoRevalidateis enabled.
Webhooks are optional. In pull mode (
api_reader/dynamic_readerarchitecture in the Connect wizard), your destination can ignore webhooks and fetch new posts from the Reader API on its own ISR/SWR interval.
When Mentionwell fires
| Delivery setting | Path Mentionwell POSTs to | Payload |
|---|---|---|
publishEndpoint in webhook_push mode |
Your configured publish endpoint | post.published or post.updated plus the full post object |
publishEndpoint in direct_api mode |
Your configured publish endpoint | { siteSlug, post } (no event wrapper) |
revalidateEndpoint with autoRevalidate: true |
Your configured revalidate endpoint | post.revalidate, post.updated, or post.deleted, a small post summary, and paths to refresh |
| Wizard Test & save | Your configured publish endpoint | post.test event with a stub post; X-MentionWell-Test: 1 header set |
Set these by opening the Connect-destination wizard — it pre-fills your secret and validates the connection. Manual config lives in Integration → Reconfigure delivery for advanced cases.
Request headers Mentionwell sends
Every webhook (publish, revalidate, or test) includes:
| Header | Value | Notes |
|---|---|---|
Content-Type |
application/json |
|
Authorization |
Bearer <readApiKey> |
Same mw_read_... key your destination uses to read the API. Optional to verify; the signature is the security boundary. |
X-MentionWell-Signature |
hex HMAC-SHA256 of the raw body using your per-site whsec_... |
Required to verify before trusting the payload. |
Idempotency-Key |
sha1(siteId:slug:updatedAt) |
Only on webhook_push and direct_api publish events. Use to de-duplicate retries. |
X-MentionWell-Test |
1 |
Only on test pings fired by the dashboard wizard. Skip side effects when you see this. |
Publish 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",
"html": "<article>...</article>",
"markdown": "# Five Questions...",
"publishedAt": "2026-04-21T15:00:00.000Z"
},
"sentAt": "2026-04-21T15:01:00.000Z"
}
event is post.published when the post is currently published and post.updated otherwise. Deletes are delivered to the revalidate endpoint as post.deleted (with the same paths array as a normal revalidate) so the destination can purge the post URL and refresh the listing.
The full post object in publish payloads includes everything the Reader API GET .../posts/<slug> endpoint returns: metaTitle, metaDescription, excerpt, html, markdown, featuredImage, readingTime, tags, category, tldr, toc, faqs, canonicalUrl, schema.jsonLd, and the timestamps. The example above shows only the most-used fields — your destination receives the full record.
Test ping (from the Connect wizard)
When you click Save & test in the wizard, Mentionwell fires a single test event so you can verify the receiver is wired up before any real publish lands:
{
"event": "post.test",
"siteSlug": "your-site-slug",
"sentAt": "2026-05-18T12:00:00.000Z",
"post": {
"slug": "mentionwell-connection-test",
"title": "Mentionwell connection test",
"html": "<p>This is a test ping — it should be ignored, not published.</p>",
"markdown": "This is a test ping.",
"publishedAt": "2026-05-18T12:00:00.000Z"
}
}
The test ping also sets X-MentionWell-Test: 1. Your receiver should treat event === "post.test" or that header as a connection check and respond 2xx without writing the post anywhere.
Revalidate payload
{
"event": "post.revalidate",
"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"
},
"paths": ["/blog", "/blog/five-questions-to-ask-before-you-buy"]
}
Always parse the body as raw text first (you need the exact bytes for signature verification), then JSON.parse it.
Signature
Every webhook request includes the Mentionwell signature header:
X-MentionWell-Signature: <hex hmac-sha256(rawBody, MENTIONWELL_WEBHOOK_SECRET)>
HTTP header names are case-insensitive, so reading x-mentionwell-signature (lowercase) is fine.
Verify it before trusting the payload.
Node.js
import { Buffer } from "node:buffer";
import { createHmac, timingSafeEqual } from "node:crypto";
export async function POST(req: Request) {
const raw = await req.text();
const sig = req.headers.get("x-mentionwell-signature") ?? "";
const expected = createHmac("sha256", process.env.MENTIONWELL_WEBHOOK_SECRET!)
.update(raw)
.digest("hex");
const verified =
sig.length === expected.length &&
timingSafeEqual(Buffer.from(sig, "utf8"), Buffer.from(expected, "utf8"));
if (!verified) return new Response("invalid signature", { status: 401 });
const { event, siteSlug, post, paths } = JSON.parse(raw);
// post.slug, post.title, post.publishedAt
// event is "post.published", "post.updated", "post.revalidate", or "post.deleted"
// if paths exists, revalidate those paths; otherwise sync the full post payload.
}
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 during the publish flow. A delivery is considered successful if your endpoint returns a 2xx response.
If it fails (non-2xx or network error), 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, use the dashboard retry control where available or republish the post. Future versions will add automatic retries with backoff — track via the deliveryStatus field if you need to backfill manually.
If your endpoint is unreliable, prefer pull mode: your destination reads the Reader API on its own ISR/SWR cycle and can never miss a publish.
Where to find the secret
Open the Connect-destination wizard — your webhook secret is shown on the Setup step with a copy button. The secret looks like whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (whsec_ prefix plus 48 hex chars).
The webhook secret is different from the API key. The API key (
mw_read_...) authorises reading posts; the webhook secret (whsec_...) authenticates outbound pushes from Mentionwell. Both are derived per-site — they're the same value every time you view them, but they only exist for this site.