FeedbackJar

Webhooks

Webhooks let FeedbackJar notify your own systems in real time — sync new posts to Slack, open a Linear issue when a post’s status changes, or trigger a Zapier/Make workflow — without polling the REST API.

Set up webhooks under Settings → Webhooks in your project.

Events

EventFired when
post.createdA new post is submitted to any board
post.status_changedA manager changes a post’s status (e.g. OPENIN_PROGRESS)
comment.createdA public comment is added to a post. Internal/pinned notes are never sent.
member.addedSomeone joins the project as a portal member
member.removedA manager removes a member from the project
tag.createdA new tag is created
tag.deletedA tag is deleted
board.createdA new board is created
board.deletedA board is deleted

Bulk operations — like the Canny importer — never trigger these events. Importing thousands of historical posts, comments, boards, tags, or authors will not flood your webhook endpoint; only actions a person takes in the live product fire events.

Payload

Every delivery is a POST request with a JSON body shaped like this:

json
{
  "event": "post.created",
  "createdAt": "2026-07-04T10:00:00.000Z",
  "data": {
    "postId": "cm1abc123",
    "title": "Dark mode support",
    "status": "OPEN",
    "boardId": "cm1board1"
  }
}

The data shape depends on the event — post.status_changed includes previousStatus/newStatus, comment.created includes commentId, postId, content, and authorName, member.added/member.removed include userId and role, tag.created/tag.deleted include tagId and name, and board.created/board.deleted include boardId, name, and slug.

Headers

HeaderDescription
Content-TypeAlways application/json
X-Feedbackjar-EventThe event name, e.g. post.created
X-Feedbackjar-SignatureOnly present if signature verification is enabled (see below)

Signature verification

When you create a webhook, you can toggle Require signature verification (on by default). If enabled, you’ll be shown a signing secret once (whsec_...) — save it, it can’t be retrieved again, but you can generate a new one at any time from the webhook’s settings.

Every request then includes an X-Feedbackjar-Signature header formatted like Stripe’s:

plaintext
t=1735689600,v1=5257a869e7bfe...
  • t — the Unix timestamp (seconds) the request was signed at
  • v1 — an HMAC-SHA256 hex digest of {t}.{raw request body}, keyed with your signing secret

To verify a request, recompute the same HMAC and compare it to v1. Reject requests where the timestamp is more than 5 minutes old, to guard against replay.

Node.js

js
import crypto from "node:crypto";

function verify(secret, signatureHeader, rawBody) {
  const parts = Object.fromEntries(
    signatureHeader.split(",").map((p) => p.split("="))
  );
  const { t, v1 } = parts;

  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody}`)
    .digest("hex");

  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

Python

python
import hashlib
import hmac
import time

def verify(secret: str, signature_header: str, raw_body: str) -> bool:
    parts = dict(p.split("=") for p in signature_header.split(","))
    t, v1 = parts["t"], parts["v1"]

    if abs(time.time() - int(t)) > 300:
        return False

    expected = hmac.new(
        secret.encode(), f"{t}.{raw_body}".encode(), hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected, v1)

If you’d rather skip verification (e.g. sending to an internal tool on a private network you already trust), turn the toggle off when creating the webhook — the X-Feedbackjar-Signature header is simply omitted.

Retries

If your endpoint doesn’t respond with a 2xx status (or times out after 10 seconds), the delivery is retried with exponential backoff, up to 6 attempts spread over roughly 30 minutes. After 20 consecutive failed deliveries, the webhook is automatically disabled — you can re-enable it from the settings page once your endpoint is healthy again.

Testing

Use the Send test event button next to any webhook to fire a one-off webhook.test event immediately, without waiting for a real post or comment. The response status (or error) is shown right away.

Security

Webhook URLs must use https:// and cannot point at localhost, private/internal IP ranges, or cloud metadata endpoints — this is enforced both when you add a webhook and on every delivery.