Step 1 — Have an endpoint ready
You need a URL that acceptsPOST with a JSON body and answers with a 2xx status. Anything
outside 200–299 counts as a failed delivery.
The endpoint must be reachable from the public internet.
localhost works only while you are
testing against a local SeoSorted install.Step 2 — Connect in SeoSorted
Project Settings → Integrations → Webhook → Connect.
The webhook connect form
string
required
Where we POST, for example
https://api.yourapp.com/seosorted/articles.string
At least 16 characters. Leave it blank and we generate one for you — the usual choice.
string
A label for your own reference, e.g. “Production blog publisher”.

Short secrets are caught up front
Step 3 — Save the signing secret
If we generated the secret, it is shown once, immediately after connecting, as Webhook connected with awhsec_… value and a Copy button.

Copy the signing secret — it is shown once
Step 4 — Send a test delivery
Open the Webhook card’s ⋮ menu and choose Send test. It posts atest event with a
realistic payload and tells you exactly what your endpoint replied.

The connected Webhook card
Step 5 — Publish
Open an article, click Publish, then Publish now next to Webhook. The dialog confirms Article Published — “Successfully delivered to your webhook endpoint”.
A webhook publish confirms delivery
publishedUrl, url, link or permalink, we
store that as the article’s live URL and the dialog shows a View article button. Relative
paths are resolved against your endpoint URL.
What gets sent
The body carries the article’s title, slug, meta fields, featured image URL and the body as both
Markdown and HTML — see the payload reference. The article’s
JSON-LD schema is not included.
Re-publishing, unpublishing and deleting
- Re-publish sends
article.updatedwith the full article. Upsert onarticle.idso it replaces the post you stored at publish time. - Unpublish sends
article.unpublished. Answer2xxonce the post is off your site; otherwise the article stays Published in SeoSorted. After a successful unpublish, the next publish sendsarticle.publishedagain. - Deleting the article in SeoSorted sends
article.deleted. Nothing else is removed for you — your handler decides what to do.
Verifying the signature
Every request carries these headers:
The signature is an HMAC-SHA256 of
<t>.<raw request body> keyed with your signing secret, where
t is the Unix timestamp in the same header.
Delivery behaviour
- Timeout: 15 seconds. Reply quickly and do the slow work asynchronously.
- Retries:
article.published,article.updatedandarticle.unpublishedrun through our job queue. A non-2xxreply or a timeout fails the attempt, and the job is retried up to 3 attempts in total with exponential backoff starting at 5 seconds. If every attempt fails, the publish (or unpublish) fails and the dashboard shows the error. - Fire-and-forget:
article.deleted,article.updatedsent on edit, andtestare sent once and never retried. - Health: after 5 failed deliveries within an hour, the connector is marked Error. Its card then shows Retry instead of the ⋮ menu, and nothing is sent until you reconnect.
- Duplicates: every attempt gets a new delivery id, so
X-SeoSorted-Deliveryis not an idempotency key. If your endpoint processed a request but replied too late, the retry arrives with a different id. Deduplicate onarticle.id+event(and make your handler an upsert).
Tracking AI crawlers
Track AI crawlers on the site that serves the published pages, not on the webhook receiver. Pick your framework and host in Which option to pick.Common problems
“Must be at least 16 characters — or leave it blank and we'll generate one.”
“Must be at least 16 characters — or leave it blank and we'll generate one.”
Supply a longer signing secret, or leave the field blank and we’ll generate a strong one.
“Test failed: …”
“Test failed: …”
The test reached nothing, or your endpoint answered with a non-
2xx status. The message
after Test failed: names the cause — see the table under Step 4.Signature verification always fails
Signature verification always fails
Almost always because the HMAC was computed over a re-serialized body. Sign the raw bytes
exactly as received, and confirm you’re using the secret shown when the webhook was
connected — reconnecting with a blank secret generates a new one.
The same article arrived twice
The same article arrived twice
A retry after a slow or failed reply. Deduplicate on
article.id + event, not on the
delivery id.
