Webhooks
Have Postopus send workspace events, such as a post published or failed, to Slack, Zapier or your own service, signed so you can check they are real.
A workspace webhook sends an HTTP POST to a URL you choose each time an event you picked happens in the workspace: a Slack incoming webhook, a Zapier hook or your own service.
Set it up#
- In the workspace switcher, choose Workspace settings, then Notifications.
- Under Workspace webhook, paste your Endpoint URL.
- Turn on the events you want and make sure Active is on.
- Choose Save webhook. Postopus shows the Signing secret.
- Choose Send test to send a
testevent and check your receiver gets it.
Workspace settings are open to owners and admins. Remove deletes the webhook. Under the settings, Last delivery shows when the last event went out and how it went.
Events#
| Event | Sent when | payload |
|---|---|---|
post.published |
A post finished publishing. | postId, snippet (the first 140 characters), status |
post.failed |
A post failed, or failed on some of its accounts. | postId, snippet, status (failed or partially_failed) |
digest.ready |
A daily digest was generated for the workspace. | digestDate, angles (titles) |
import.completed |
An import of past X posts finished. | socialAccountId, imported, skipped, repliesCaptured |
test |
You chose Send test. | message |
In the settings these are Post published, Post failed, Daily digest ready and Import completed.
What is sent#
Every delivery is a JSON body:
{
"type": "post.published",
"teamId": "your-workspace-id",
"timestamp": "2026-11-03T09:00:04.512Z",
"payload": {
"postId": "post-id",
"snippet": "We shipped threads today.",
"status": "published"
}
}
With these headers:
Content-Type: application/jsonX-Postopus-Event: the event typeX-Postopus-Signature: the signature (below)
Check the signature#
X-Postopus-Signature is the HMAC-SHA256 of the raw request body, keyed with your signing secret, as lowercase hex. Compute it over the body exactly as received, before parsing it, and compare. For example, in Node.js:
import { createHmac, timingSafeEqual } from "node:crypto";
function isFromPostopus(rawBody, signature, secret) {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
return signature.length === expected.length && timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
Reject a request whose signature does not match.
Delivery and retries#
Postopus sends each event once and waits up to 5 seconds for your endpoint. It does not retry: if your endpoint is down, too slow or answers with an error, that event is not sent again. Last delivery shows the result (ok; http_ followed by the status code your endpoint answered, such as http_500; timeout; or error).
A webhook that fails never holds up publishing.