Durabull Documentation
Integrations

Webhook Notifications

Route Durabull alert events to HTTPS webhook endpoints with signed JSON payloads.

Webhook notifications let alert rules POST structured JSON to any HTTPS endpoint you control. Use them for custom paging, automation (Zapier, n8n), internal incident systems, or middleware that forwards alerts into Slack or PagerDuty.

Setup

You can configure webhooks in two ways:

  • Saved webhook destinations: reusable organization-level endpoints managed from settings.
  • Custom webhook URLs: one-off endpoints configured directly on an alert rule.

For reusable destinations:

  1. Open Settings → Integrations.
  2. Add a Webhook alert destination with a name and endpoint URL.
  3. Optionally add a signing secret (minimum 16 characters).
  4. Use Test to verify delivery.
  5. Open a connection's alert rule builder and choose the saved destination from a Webhook route.

For one-off endpoints, open a connection's alert rule builder, add a Webhook route, switch it to Custom URL, and enter the endpoint URL and optional signing secret.

Webhook routes are configured per alert rule, alongside email and Linear destinations. Saved destination edits apply to future alert deliveries only; deliveries already queued use the URL and signing secret snapshot captured when the alert was enqueued.

Payload format

Durabull sends versioned JSON with schemaVersion: 1.

{
  "schemaVersion": 1,
  "event": "alert.fired",
  "id": "alert-event-uuid",
  "deliveryId": "delivery-uuid",
  "occurredAt": "2026-05-25T12:00:00.000Z",
  "organization": { "id": "org_123", "slug": "acme" },
  "connection": { "id": "conn_123", "name": "Production Redis" },
  "rule": { "id": "rule_123", "name": "High failure rate", "type": "failure_rate" },
  "queue": { "name": "email-send" },
  "alert": {
    "status": "firing",
    "summary": "Failure rate exceeded threshold",
    "context": { "jobId": "42", "failedReason": "SMTP timeout" },
    "firedAt": "2026-05-25T12:00:00.000Z",
    "dedupeKey": null
  },
  "links": {
    "dashboard": "https://app.durabull.io/acme/c/conn_123/queues/email-send",
    "job": "https://app.durabull.io/acme/c/conn_123/queues/email-send/jobs/42",
    "muteRule": "https://app.durabull.io/acme/c/conn_123/alerts?ruleId=rule_123"
  }
}

Test deliveries use event: "alert.test" with synthetic context.

Durabull does not include full BullMQ job.data payloads in webhook bodies.

Request headers

HeaderDescription
Content-Typeapplication/json
User-AgentDurabull-Alerts/1.0
Idempotency-KeyAlert event id — use to dedupe retries
X-Durabull-Delivery-IdDelivery attempt id
X-Durabull-TimestampUnix seconds (when signing is enabled)
X-Durabull-Signaturesha256=<hex> HMAC (when signing is enabled)

Verifying signatures

When a signing secret is configured, verify:

signature = HMAC-SHA256(secret, "{timestamp}.{rawBody}")

Reject requests older than five minutes to limit replay attacks.

import { createHmac, timingSafeEqual } from 'node:crypto'

function verifyDurabullWebhook(rawBody: string, headers: Headers, secret: string): boolean {
  const timestamp = headers.get('x-durabull-timestamp')
  const signature = headers.get('x-durabull-signature')
  if (!timestamp || !signature) return false
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false

  const expected = createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex')

  const provided = signature.replace(/^sha256=/, '')
  return timingSafeEqual(Buffer.from(provided), Buffer.from(expected))
}

Delivery behavior

  • Durabull uses at-least-once delivery with exponential backoff retries.
  • Respond with any 2xx status to acknowledge receipt.
  • 408, 429, and 5xx responses are retried.
  • Most other 4xx responses are treated as permanent failures.
  • Requests time out after 10 seconds.
  • Due retry attempts are swept by the existing alert monitor, so retries can continue even after the original alert is no longer actively firing.
  • Retry attempts stop after 7 days from the first delivery enqueue. The delivery row is marked permanently failed so dead endpoints do not retry forever.

Security notes

  • Production webhook URLs must use HTTPS.
  • Durabull blocks private and localhost targets (SSRF protection).
  • Saved destination signing secrets are encrypted at rest and masked in API responses.
  • Custom per-rule webhook signing secrets remain scoped to that alert rule and are masked in API responses after save.

For local development only, set DURABULL_WEBHOOK_ALLOW_HTTP=true to permit HTTP webhook URLs.