Agent skill
New Relic Webhooks Skill
Receive and authenticate New Relic alert webhooks. Use when setting up a New Relic Webhook destination for workflow notifications, verifying HTTP Basic authentication, debugging 401s, or handling CREATED, ACTIVATED, CLOSED and acknowledged issue notifications from your own payload template.
Install this skill
npx skills add hookdeck/webhook-skills --skill new-relic-webhooks
New Relic Alerts sends an HTTP POST to a Webhook destination when a workflow fires for an issue. Webhooks are not signed. The destination can send HTTP Basic credentials (Authorization: Basic base64(username:password)), and your endpoint authenticates the request by comparing them with the ones you stored. This skill covers Basic authentication only; the Bearer token and custom headers options are alternatives it does not cover.
The body is JSON rendered from a Handlebars template that you write in the workflow, so there is no fixed event field. The examples use an illustrative template with issueId, title, state, acknowledged, priority and issuePageUrl; adapt them to your own. state is New Relic's state variable, the issue's life cycle state (CREATED, ACTIVATED, CLOSED), and acknowledged is its isAcknowledged boolean (workflow template variables).
Security note: a static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Use HTTPS only, and rotate the credential in the destination and in your endpoint if it leaks.
When to Use This Skill
- How do I receive New Relic alert webhooks?
- How do I verify the Basic auth credentials on a New Relic Webhook destination?
- Does New Relic sign webhook payloads? (No: use Basic authentication)
- How do I handle issue
CREATED,ACTIVATEDandCLOSEDnotifications, and acknowledgements? - Why does my New Relic webhook endpoint return 401?
Verification (core)
const crypto = require('crypto');
// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
const digest = (b) => crypto.createHash('sha256').update(b).digest();
const safeEqual = (a, b) => crypto.timingSafeEqual(digest(a), digest(b));
function verifyNewRelicRequest(headers, username, password) {
if (!username || !password) return false; // never accept when unconfigured
const m = /^basic\s+([A-Za-z0-9+/]+={0,2})\s*$/i.exec(headers['authorization'] || '');
if (!m) return false;
const decoded = Buffer.from(m[1], 'base64');
const colon = decoded.indexOf(0x3a); // split on the FIRST colon
if (colon === -1) return false;
const userOk = safeEqual(decoded.subarray(0, colon), Buffer.from(username));
const passOk = safeEqual(decoded.subarray(colon + 1), Buffer.from(password));
return userOk && passOk; // both evaluated, no short-circuit
}
- Header:
Authorization: Basic base64(username:password); the scheme is case-insensitive. - Return
401on a missing or malformed header or a mismatch,400for a body that isn't a JSON object,200once handled. - Read the body raw (
express.raw({ type: '*/*' })) and authenticate before parsing it. - In Python compare bytes with
hmac.compare_digest(encode both sides); passingstrraises on non-ASCII.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Illustrative Payload
New Relic renders whatever Handlebars template you configure, so these fields are an example, not a fixed schema (see references/setup.md for the template).
state | Meaning |
|---|---|
CREATED | The issue was created |
ACTIVATED | The issue is active (opened) |
CLOSED | The issue closed |
These are the life cycle values New Relic documents for its state variable. Acknowledgement is not a state: the template sends isAcknowledged (true/false) as acknowledged. See New Relic's workflow template variables.
Other fields in the example: issueId, title, priority, issuePageUrl.
Environment Variables
NEW_RELIC_WEBHOOK_USERNAME=your-username # Basic auth username on the Webhook destination
NEW_RELIC_WEBHOOK_PASSWORD=your-password # Basic auth password on the Webhook destination
Local Development
New Relic can't reach localhost. Tunnel with the Hookdeck CLI (no account required):
npx hookdeck-cli listen 3000 new-relic --path /webhooks/new-relic
Use the printed URL as the Endpoint URL of the Webhook destination.
Resources
- references/overview.md - What New Relic alert webhooks are and the illustrative payload
- references/setup.md - Create the destination, Basic auth and payload template
- references/verification.md - Basic auth check details, gotchas, debugging 401s
- examples/ - Runnable Express, Next.js and FastAPI handlers with tests