Quick answer: Add a webhook under Integrate > Webhooks in Bugnet, choose the events (bug_created, bug_updated, comment_added) and set a signing secret. Each delivery is a JSON POST with X-Bugnet-Event, a stable X-Bugnet-Delivery id and an X-Bugnet-Signature HMAC you verify against the raw body. Failed deliveries retry after 1, 5, 25 and 125 minutes. Webhooks are on every Bugnet plan.

Built-in integrations cover the usual tools, but every studio has something of its own: an internal dashboard, a Discord bot with custom logic, a build pipeline that should halt when a crash spikes, or a planner Bugnet does not connect to yet. Webhooks are how you plug those in. Here is everything you need to consume them safely.

Events

EventFires when
bug_createdA new bug report is filed: from the SDK, the web form or a team member. A report stacked onto an existing bug as a duplicate does not fire it.
bug_updatedA bug's title, description, status, priority, category, assignee or visibility changes.
comment_addedA comment is added to a bug.

Payload

{
  "event": "bug_created",
  "timestamp": "2026-03-13T12:00:00Z",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "report_number": 42,
    "title": "Game crashes on level 5",
    "description": "Crash when opening the inventory during the boss fight.",
    "priority": "critical",
    "category": "crash",
    "project_slug": "a1b2c3-my-game"
  }
}

comment_added deliveries carry comment_id, report_number, title, body, is_internal and project_slug in data.

Headers

Verifying the signature

The signature is the HMAC-SHA256 of the raw request body, keyed with your secret and hex-encoded. Compute it over the exact bytes you received, before parsing the JSON, and compare in constant time:

Node.js
const crypto = require('crypto');
// rawBody must be the exact bytes received, e.g. express.raw({ type: 'application/json' })
function verifyBugnet(rawBody, header, secret) {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(expected), b = Buffer.from(header || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Python
import hashlib, hmac

def verify_bugnet(raw_body: bytes, header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header or "")

Reject requests with a missing or mismatched signature. Webhooks saved without a secret are sent unsigned, so always set one in production.

Delivery and retries

Ideas for what to build

Create a free Bugnet project to add a webhook; the full reference is in the webhook docs. To send data into Bugnet instead, see the bug report API.

Frequently asked questions

What events can Bugnet send by webhook?

bug_created for new bug reports, bug_updated when a bug's title, description, status, priority, category, assignee or visibility changes, and comment_added for new comments.

How do I verify a Bugnet webhook?

Compute the HMAC-SHA256 of the raw request body with your signing secret, hex-encode it, prefix it with sha256= and compare it in constant time with the X-Bugnet-Signature header.

What happens if my endpoint is down?

Bugnet retries after 1, 5, 25 and 125 minutes, up to 5 attempts in total, then marks the delivery failed. The Deliveries view shows the last 50 attempts.

Can I receive the same event twice?

Occasionally, because of retries. Deduplicate on the X-Bugnet-Delivery header, which stays the same across retries of one event.

Are webhooks available on the free plan?

Yes. Webhooks are included on every Bugnet plan.

A webhook you cannot verify is just a stranger posting to your server. Set the secret.