Help/Publishing
Publishing to your own server (webhook)
Send each finished page to an address you run, so your own code or an agent can put it live. What we send, how to check it came from us, and what to answer.
If your site is not WordPress, or you want an agent or your own code to decide what happens to a page, connect an address you run. When a page is published, we send it there instead of to WordPress.
Setting it up
- Enter your address under Your own server. It has to be
https://, and it has to be reachable from the internet. - We create a signing secret and show it once. Copy it to your server.
- Press Send a test. We send a signed
ping; your server answers with any 2xx status.
Saving the address again creates a new secret, which is how you rotate one. A site publishes through one connection, so saving your own server replaces a WordPress connection on the same site, and the reverse.
What we send
A POST with a JSON body, sent when someone presses Publish in the editor or an agent calls publish_draft:
{
"type": "page.publish",
"timestamp": "2026-09-26T14:03:11.000Z",
"data": {
"draft_id": "ed9be860d2268472",
"site_host": "example.com",
"status": "publish",
"title": "How to choose a travel shoe",
"slug": "choose-travel-shoe",
"html": "<p>…</p>",
"markdown": "…",
"excerpt": "…",
"meta_description": "…",
"schema_json_ld": "{\"@context\":\"https://schema.org\", …}",
"featured_image_url": "https://…/image.webp",
"images": ["https://…/image.webp"],
"question": "best womens travel slip on shoes"
}
}
statusispublish(put it live) ordraft(keep it unpublished).htmlis the page body without the title. Puttitlein your page's heading.schema_json_ldis a JSON-LD string, ornull. Place it in the page's<head>inside a<script type="application/ld+json">tag.- Images are hosted by us. Copy them to your own storage if you would rather not depend on our links.
The test sends "type": "ping" with only site_host in data.
Checking it came from us
Every request carries three headers, in the Standard Webhooks format:
webhook-id: a unique id for the message.webhook-timestamp: seconds since 1970.webhook-signature:v1,then a base64 HMAC-SHA256 of{webhook-id}.{webhook-timestamp}.{raw body}, keyed with your secret base64-decoded after itswhsec_prefix.
Any Standard Webhooks library checks this in one line. In Node:
import { Webhook } from "standardwebhooks";
const wh = new Webhook(process.env.RN_WEBHOOK_SECRET);
const event = wh.verify(rawBody, headers); // throws if the signature or timestamp is wrong
Check against the raw request body, before parsing it: re-serialising the JSON changes the bytes. Reject timestamps more than five minutes old.
What to answer
Answer with a 2xx status and a JSON body:
{ "url": "https://example.com/choose-travel-shoe", "id": "your-id", "edit_url": "https://…" }
For a live publish, url is required: it is the address we record on the question board, and the address the weekly checks credit when an AI engine names the page. Without it the publish is reported as failed. id and edit_url are optional.
We wait 20 seconds. A redirect, a timeout or any status outside 2xx is shown to the person who pressed Publish as a failure, with the reason.
Updated September 26, 2026