Agent skill
FireHydrant Webhooks Skill
Receive and verify FireHydrant webhooks. Use when setting up FireHydrant webhook handlers, debugging fh-signature verification, or handling incident management events such as incident, change_event, and signals_alerts payloads.
Install this skill
npx skills add hookdeck/webhook-skills --skill firehydrant-webhooks
FireHydrant (incident management) sends an HTTP POST with a JSON body to your endpoint whenever a subscribed event happens. Each request carries an fh-signature header: the hex-encoded HMAC-SHA256 of the raw request body, keyed with the Secret you set when creating the webhook.
When to Use This Skill
- How do I receive FireHydrant webhooks?
- How do I verify the FireHydrant
fh-signatureheader? - How do I handle incident, change event, or Signals alert webhooks from FireHydrant?
- Why is my FireHydrant webhook signature verification failing?
Verification (core)
The signature is a bare hex digest (no sha256= prefix) of the raw body. There is no timestamp or message ID in the signed content.
const crypto = require('crypto');
function verifyFireHydrant(rawBody, signature, secret) {
if (!signature) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(signature, 'utf8');
const b = Buffer.from(expected, 'utf8');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
valid = hmac.compare_digest(signature.encode(), expected.encode())
In Express, read the body with express.raw({ type: '*/*' }) so the signature verifies whatever Content-Type FireHydrant sends. Parse the JSON only after verification passes.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Event Types
Every payload has two top-level keys: data and event. Identify the event with event.resource_type and event.operation.
event.resource_type | event.operation | Triggered When |
|---|---|---|
incident | UPDATED | Any change to an incident (fields, milestones, tasks, roles, notes, chat, teams) |
change_event | updated | A change event is created or updated |
signals_alerts | CREATED, UPDATED | A Signals alert is created, or its state changes (BETA) |
Operation casing differs between resource types (UPDATED vs updated), so compare case-insensitively. See references/overview.md for payloads.
Environment Variables
# The Secret field on Settings → Webhooks → your webhook
FIREHYDRANT_WEBHOOK_SECRET=your_webhook_secret_here
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 firehydrant --path /webhooks/firehydrant
Use the printed URL as the webhook URL in FireHydrant (Settings → Webhooks).
Reference Materials
- references/overview.md - FireHydrant webhook concepts, resource types, payloads
- references/setup.md - Create a webhook and set the Secret
- references/verification.md - Signature verification details and gotchas