Webhooks: How to Know a Post Actually Went Live
Polling a status endpoint every few minutes to find out if a post went live is a waste of a request budget and a guarantee that you find out late. A webhook exists so your own systems hear about the publish the moment it happens instead of asking. Here is exactly how PostSider’s webhook works, verified against the actual delivery code, not the marketing description of it.
Subscribing happens in Settings, scoped per channel if you want it that way
A webhook lives under Settings, Webhooks in the dashboard, and it is organization-scoped: the URL you register only fires for posts published inside that organization. You can leave it unscoped so it fires for every connected channel, or narrow it to a specific set of integrations if you only care about, say, the LinkedIn and X publishes and not the other 28 networks in the workspace. There is also a send-test button on the same screen, which posts a real sample payload to your URL on demand, so you can build the receiving endpoint before a real post ever triggers it.
The payload is an array of post objects, and the event lives in a header
This is the part that catches people who assume a webhook body looks like {event, postId, status}. It does not. The body PostSider sends is an array, each entry shaped like a post record: id, content, publishDate, releaseURL, state, and a nested integration object carrying id, name, providerIdentifier, picture, and type. The event name is not inside that JSON at all. It arrives as the X-Postsider-Event header, currently always post.published, alongside an X-Webhook-Attempt header telling you which try this is.
Write your parser against the header for routing logic and against the array for content. Code that expects a single object with an event field buried inside it will silently break the first time it tries to read payload.event and gets undefined.
There is no failure event, because the webhook only fires on success
Worth stating plainly since it shapes how you should design around this: PostSider does not fire a webhook when a publish fails. The webhook call happens exclusively from the success path of the publish workflow. A failed publish sets the post’s own state to ERROR on the record, visible if you read post status through the API, but nothing gets pushed to your endpoint about it. If your integration needs to know about failures, poll status for posts you scheduled, or check them on your own cadence. Do not build a failure handler that waits on a webhook event that will never arrive.
Retries are 3 attempts with exponential backoff, and 4xx never retries
Delivery retries up to 3 times total, with a 1 second wait before the second attempt and a 2 second wait before the third. That retry only kicks in for a 5xx response or a network-level failure, the kind of thing that suggests your endpoint had a transient problem. A 4xx response is read as your side deliberately rejecting the payload, malformed auth, wrong shape, whatever it is, so PostSider logs it and does not try again. If your endpoint is flaky enough to 500 under normal load, you have up to two extra chances before the event is dropped. Design your receiver to return a fast 2xx once it has durably queued the payload, not after it has finished processing it, so a slow downstream step does not accidentally look like a failure and burn a retry.
Three things worth building on the webhook once it lands
Log to a warehouse. The simplest use: append every payload to wherever you already keep events, so “did this post actually go out” becomes a query instead of a guess six months from now.
Notify a Slack channel. A one-line message with the post’s integration.name and a link built from releaseURL turns a silent publish into something a team actually sees land, which matters more than it sounds like it should for anyone not staring at the dashboard all day.
Trigger follow-up content. A published post is sometimes the cue for something else: a cross-post reminder, a cue to draft a reply thread, a note to check performance in a day. The webhook is the trigger, not the logic, so keep the handler thin and push the actual work into whatever queue you already run.
SSRF protection is real, but there is no signature yet
Two things are true about outbound safety here, and they are not the same thing. First, the good news: registering a webhook URL is validated against SSRF at both ends, HTTPS is required, and localhost, loopback, private, link-local, and CGNAT ranges are blocked on both IPv4 and IPv6, re-checked again at the moment of actual delivery so a DNS answer that changes after registration cannot sneak a request to an internal address. That protection exists to stop PostSider’s own servers from being tricked into hitting something they should not, which matters if you ever consider letting end users register their own webhook targets.
Second, the honest gap: outbound payloads are not HMAC-signed today, so your receiving endpoint has no built-in way to cryptographically verify a request actually came from PostSider rather than someone who guessed your URL. Until that ships, treat the URL itself as the secret. Do not publish it, do not put it in client-side code, and if you need stronger verification right now, put the endpoint behind an API gateway with its own auth in front of it.
Build the receiver assuming at-most-3 tries, not exactly-once
Every design decision above points at the same rule: build your receiver to be safely callable more than once, acknowledge fast, and do not wait on an event that this system does not send. Return a 2xx the moment you have durably stored the payload, keep any real processing out of the request path, and if you need failure visibility, poll for it instead of waiting for a push. I wrote about the broader shape of building against PostSider’s API, including the rate limits this webhook shares a budget with, in scheduling posts with a social media API. The same discipline applies here: read the actual behavior before you write the integration, not the behavior you assumed a webhook would have.
Frequently asked questions
What does a PostSider webhook fire on?
A successful publish. The event arrives with an X-Postsider-Event header set to post.published. There is no separate failure event today. A publish that errors out sets the post's own state to ERROR on the record, which you catch by reading post status through the API, not through a webhook.
How many times does PostSider retry a webhook delivery?
Up to 3 attempts, with exponential backoff of 1 second then 2 seconds between tries. Retries only happen on 5xx responses or network errors. A 4xx from your endpoint is treated as your side rejecting the payload on purpose, so it is logged and not retried.
Is the webhook payload signed so I can verify it came from PostSider?
Not yet. HMAC signing on outbound payloads is on the roadmap but not shipped. Until it is, treat the endpoint URL itself as the access control: keep it private, and rely on the SSRF-safe URL validation on the subscribe side, not a signature check on the receive side.
What does the webhook payload actually contain?
An array of post objects, not a single flat event object. Each entry has id, content, publishDate, releaseURL, state, and an integration object with id, name, providerIdentifier, picture, and type. If your code expects a single-object envelope with an event name inside the body, check the header instead, the event type lives in X-Postsider-Event, not in the JSON.