Skip to main content
An outgoing webhook is a public URL Connect POSTs to. You subscribe to events, we sign the body, you answer quickly with 2xx (including 204). Private, loopback, and link-local URLs are refused. Connect does not follow redirects — a 3xx is a failure. Create and manage endpoints in the dashboard or the Webhooks API. Creating one does not ping the URL; send a test when you want to.

Events

There is no publishing event and no wildcard. Immediate publish goes draft → publishing (silent) → outcome. A due scheduled post does the same. Edits that do not change status send nothing.

What arrives

A small envelope: an id, the event name, a data object, and a timestamp.
  • id is the delivery. Retries of the same attempt keep it. A replay gets a new one.
  • type is the event, or webhook.test for a ping (data is empty).
  • data on post events is the post (caption, media, per-network rows, author). On account events it is the social account.
  • created_at is this attempt. Retries keep the id and write a new timestamp — so the signature changes. Dedupe on id, not on the raw body.

Verify it is us

Connect sends X-Webhook-Signature: hex HMAC-SHA256 of the raw body, plus User-Agent: TryPost.it/1.0 (+https://trypost.it). Hash the bytes you received (not a re-serialized JSON) with the signing secret. Compare with a constant-time check.
Read the unparsed body (for example Express express.raw({ type: 'application/json' })) and only then JSON.parse.
The secret is shown when you create, open, or rotate a webhook — not when you list them. Rotate invalidates the previous secret immediately, including the next retry of an in-flight delivery.

If deliveries fail

Connect pauses the webhook after repeated failures. You turn it back on; you cannot set “paused” yourself. Replay still sends even while it is paused or disabled.