Agent skill

Honeycomb Webhooks Skill

Receive and authenticate Honeycomb webhooks. Use when setting up a Honeycomb webhook recipient for Triggers, SLO burn alerts or Anomaly Detection, checking the X-Honeycomb-Webhook-Token Shared Secret, debugging 401s, or deduplicating deliveries with X-Honeycomb-Webhook-Delivery-ID.

Install this skill

npx skills add hookdeck/webhook-skills --skill honeycomb-webhooks


Honeycomb (observability) can notify a webhook when a Trigger fires, an SLO burn alert fires or Anomaly Detection raises a signal. Webhooks are not signed. Every request carries the webhook integration's Shared Secret as plain text in the X-Honeycomb-Webhook-Token header, and your endpoint authenticates the request by comparing that header with the secret you stored.

Hookdeck setup note: Set a Shared Secret on the Honeycomb webhook. Webhooks without one send nothing to verify.

A static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Use HTTPS and rotate the Shared Secret if it leaks.

When to Use This Skill

  • How do I receive Honeycomb webhooks?
  • How do I verify the X-Honeycomb-Webhook-Token header?
  • Does Honeycomb sign webhook payloads? (No: use the Shared Secret)
  • How do I handle Honeycomb trigger, SLO burn alert or anomaly notifications?
  • How do I deduplicate Honeycomb deliveries with X-Honeycomb-Webhook-Delivery-ID?
  • Why does my Honeycomb webhook endpoint return 401?

Verification (core)

const crypto = require('crypto');

// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
function safeEqual(a, b) {
  const ha = crypto.createHash('sha256').update(String(a)).digest();
  const hb = crypto.createHash('sha256').update(String(b)).digest();
  return crypto.timingSafeEqual(ha, hb);
}

function verifyHoneycombRequest(headers, secret = process.env.HONEYCOMB_WEBHOOK_SECRET) {
  if (!secret) return false;                              // never accept when unconfigured
  const received = headers['x-honeycomb-webhook-token'];  // whole value, no prefix
  return Boolean(received) && safeEqual(received, secret);
}
  • Header: X-Honeycomb-Webhook-Token: <Shared Secret>, sent on every request when a secret is set. Look it up case-insensitively and compare the whole value.
  • Return 401 on a missing header or mismatch, for every HTTP method, before touching the body.
  • Read the body raw (express.raw({ type: '*/*' })) and parse it only after the check. The body is application/json, but an empty body must not break the handler.
  • Python: hmac.compare_digest on bytes (encode both sides; never pass str, which raises on non-ASCII).

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

HTTP Methods

Honeycomb's docs don't name the HTTP method, so the examples accept GET, POST, PUT, PATCH and DELETE on the webhook route and check the credential first for each. Hookdeck's Honeycomb source pre-selects POST without managing the method, so any other method Honeycomb uses must also be allowed on the source.

Alert Types

Honeycomb has no event-type field. The notification kind comes from where the webhook is attached:

KindSent When
TriggerA Trigger fires or resolves
SLO burn alertA Budget Rate or Exhaustion Time burn alert fires
Anomaly DetectionAn anomaly signal fires

The default payload carries the result of the alert as JSON but isn't documented field by field, and a webhook can use a custom JSON template per alert type (Payload tab). The examples therefore classify defensively by the fields present (trigger, slo_burn_alert, anomaly, else unknown) and use clearly labelled illustrative payloads. Check a real delivery from your own webhook before relying on specific fields.

Idempotency and Timeouts

  • X-Honeycomb-Webhook-Delivery-ID is unique per delivery and stable across retries: use it to deduplicate.
  • Respond within 15 seconds; a timeout fails the delivery with no retry. Do slow work asynchronously.
  • Honeycomb retries up to three times on 408, 502, 429/503 with Retry-After, and connection failures. Other 4xx and 5xx fail without a retry, so a 401 is not retried.

Environment Variables

HONEYCOMB_WEBHOOK_SECRET=your-shared-secret   # Shared Secret from the Honeycomb webhook integration

Local Development

Honeycomb can't reach localhost. Tunnel with the Hookdeck CLI (no account required):

npx hookdeck-cli listen 3000 honeycomb --path /webhooks/honeycomb

Use the printed URL as the Webhook URL in Honeycomb.

Resources


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 10, 2026

View on GitHub →