threadliner
Integrations

Webhooks

Register an endpoint to get a POST request whenever something happens in Threadliner.

A webhook is an account-wide subscription: pick the event types you care about, and every matching event across your whole workspace gets POSTed to your URL — not scoped to one form, list, or pipeline.

This is different from the send_webhook automation action — that's a one-off POST from a single rule, only firing for events matching that rule's trigger and conditions. Registering a webhook here is broader and standing: every event of the chosen types, for as long as the webhook exists.

Registering an endpoint

  1. Go to Settings → Webhooks.
  2. Fill in Endpoint URL and check the Events you want to subscribe to.
  3. Click Create webhook.
  4. Copy the signing secret shown immediately after — it's shown exactly once and used to verify deliveries.

Payload shape

Every delivery is a POST with this JSON body:

{ "type": "<event type>", "data": { /* event-specific payload */ } }

And these headers:

Content-Type: application/json
X-Threadliner-Event: <event type>
X-Threadliner-Signature: sha256=<hex-encoded HMAC>

The 10 event types and their data payload shapes are documented in the automation trigger reference (which covers 9 of them — the 10th, campaign.sent, is webhook-only, not available as an automation trigger):

{ "campaignId": "…", "listId": "…", "sentCount": 42, "failedCount": 1 }

Verifying a delivery

The signature is an HMAC-SHA256 of the raw request body, using your webhook's signing secret, hex-encoded:

const crypto = require("node:crypto");

function isValidSignature(rawBody, signatureHeader, secret) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected));
}

Compute the HMAC over the raw, unparsed request body — not a re-serialized version of the parsed JSON, which can differ in whitespace/key order and produce a mismatch.

Retries

There's no automatic retry. Each delivery is attempted once — if your endpoint is down or times out (10 second timeout), that event is gone as far as the webhook system is concerned. Design your endpoint to respond quickly and reliably, and check View deliveries on the webhook (under Settings → Webhooks) periodically if you need to catch gaps.

Viewing delivery history

Each registered webhook has a View deliveries toggle showing recent attempts: event type, timestamp, and either the HTTP status code, or an error message (a network failure, or a timeout) if the request never got a response at all.

Deleting a webhook

Click Delete next to the endpoint under Settings → Webhooks. There's no pause/ disable — only delete.

Was this page helpful?

Last updated on

On this page