Every article, the second it goes live —
webhooked, signed, POSTed to you.
Point Ghost Writr at any https URL, choose which events it fires on, and I'll POST a signed JSON payload the moment something happens. When an article publishes I send the whole thing — title, slug, markdown, search snippet, and the live URL when I've captured one. Index it, mirror it, or trigger your own flow — it's your payload.
Add, pick, receive.
You add an endpoint.
Paste your https receiver URL in the dashboard and either bring your own signing secret or let me mint one. I show it exactly once, then store it write-only — so keep the copy you make.
You pick the events.
Choose which events this endpoint fires on: 'Article published' when a post goes live, 'Feed updated' when your content feed rebuilds. Many endpoints per site, each on its own set of events.
I POST a signed payload.
When the event fires, I POST the JSON to your URL, signed: a Webhook-Signature header (alongside Webhook-Id and Webhook-Timestamp) carrying an HMAC over the id, timestamp, and body together, so it's replay-safe. Verify it and you know it came from me — and if your endpoint blips, I retry with backoff so the event isn't lost.
Every payload is signed and delivered for real, so you can trust it's from me.
No shared inbox, no guessing whether a POST is real. Each delivery is signed over its id, timestamp, and body — you verify it with your own secret before you act, and a captured request can't be replayed.
Every delivery carries three headers — Webhook-Id, Webhook-Timestamp, and Webhook-Signature (a v1=<hex> HMAC-SHA256, keyed by your secret, over the id, timestamp, and raw body joined together). Recompute that HMAC over the exact bytes you receive, check the timestamp is recent, and compare in constant time — that's how you know it's me, and not a spoofed or replayed request. Delivery is durable, not fire-and-forget: if your endpoint errors or times out I retry with exponential backoff, keep a per-endpoint delivery log you can resend from, and auto-disable an endpoint that stays broken so failures never pile up silently. Dedupe on the Webhook-Id, since a retry reuses it. Pair this with the keyless content feed and SDKs to render or revalidate on your own site, or wire it straight into autonomous SEO so every published post lands in your stack automatically.
What lands on your endpoint.
POST https://your-site.com/hooks/ghostwritr
Content-Type: application/json
User-Agent: GhostWritr-Engine/1
Webhook-Id: 0198b3c1-7f42-7a10-9c3d-1e2f3a4b5c6d
Webhook-Timestamp: 1782032040
Webhook-Signature: v1=3f9a1c... # hmac-sha256(your-secret, id.timestamp.body)
{
"event": "article.published",
"siteId": "site_a1b2c3",
"articleId": "art_9x8y7z",
"title": "How to price a B2B SaaS",
"slug": "how-to-price-b2b-saas",
"markdown": "## Pricing anchors\n\nStart from value, not cost...",
"seoTitle": "B2B SaaS Pricing: A Practical Guide",
"seoDescription": "How to price B2B SaaS without guessing.",
"liveUrl": "https://your-site.com/blog/how-to-price-b2b-saas",
"publishedAt": "2026-07-01T09:14:00Z",
"mode": "autopilot"
} Two events, one signed pipe.
Subscribe an endpoint to either or both. Each fires post-commit, once I've actually committed the change — and you can fire a test ping any time to check your setup.
Webhooks, answered.
Verifying signatures, your secret, the events, and delivery behavior.
- How do I verify a webhook is really from Ghost Writr?
- Read the raw request body exactly as received and recompute the HMAC-SHA256, keyed by your secret, over the id, timestamp, and body joined as id.timestamp.body — then compare it in constant time to the Webhook-Signature header (a v1=<hex> value) and check the Webhook-Timestamp is recent. If both hold it's from me; otherwise reject it. Signing the timestamp and id alongside the body is what makes it replay-safe, and the SDKs ship a verifyWebhook helper that does all of this for you.
- What happens to my signing secret?
- You either bring your own (min 8 characters) or let me generate one. Either way I show it exactly once when you create the endpoint, then store it write-only — it's never displayed again. Lost it? Edit the endpoint with a new secret to rotate; leave it blank to keep the current one.
- Which events can I subscribe to?
- Two today: 'Article published', which POSTs the full article when a post goes live, and 'Feed updated', which fires after your content feed rebuilds so you can revalidate or redeploy. There's also a 'Send test' ping you trigger manually to check your receiver.
- Do you retry a failed delivery?
- Yes. If your endpoint errors or times out, I retry with exponential backoff and keep a per-endpoint delivery log — you can see every attempt and resend any delivery from the dashboard. After repeated failures a delivery is dead-lettered, and an endpoint that stays broken auto-disables so failures don't pile up silently — I'll flag it when that happens. Build receivers to be idempotent and dedupe on the Webhook-Id, since a retry reuses it.
- Can I send events to more than one place?
- Yes. Add as many endpoints per site as you like, each with its own https URL, its own secret, and its own set of events. Toggle any of them on or off, edit, or delete from the dashboard whenever you want.
- What's in the article.published payload?
- The event name, your siteId and articleId, plus the full article: title, slug, markdown body, your search snippet (sent as seoTitle and seoDescription), the live URL when I captured one (e.g. a WordPress push — headless sites build it from siteId + slug), publishedAt, and the publish mode. Enough to index it, mirror it elsewhere, or trigger your own downstream flow.
Hire the content team
that never sleeps.
Ghost Writr ships an action a day, every day. Approve with a reply, watch the graph compound.