Agent skill

Dynatrace Webhooks Skill

Receive and authenticate Dynatrace problem notification webhooks. Use when setting up a Dynatrace custom webhook integration (Classic problem notifications), verifying a secret header, debugging 401s, or handling opened and resolved problems from a payload template with placeholders like {ProblemID}, {State} and {ProblemTitle}.

Install this skill

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


Dynatrace (Classic) problem notifications can POST to a custom webhook URL when a problem opens or is resolved. Requests are not signed. The body is a payload template you write (JSON, text or XML) using placeholders such as {ProblemID}, {State}, {ProblemTitle}, {ImpactedEntity} and {ProblemImpact}; Dynatrace adds no event field of its own. You authenticate requests with a secret header you add as an Additional HTTP header on the integration.

Send the secret in a custom header, not as a token in the webhook URL. Dynatrace allows a token in the URL, but Hookdeck can't check it and URLs leak into logs.

When to Use This Skill

  • How do I receive Dynatrace problem notification webhooks?
  • How do I authenticate a Dynatrace webhook? (No signature: use a secret header)
  • How do I handle opened and resolved problems from a Dynatrace payload template?
  • Why does my Dynatrace 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 verifyDynatraceRequest(headers,
    name = process.env.DYNATRACE_WEBHOOK_HEADER || 'Authorization',
    secret = process.env.DYNATRACE_WEBHOOK_SECRET) {
  if (!secret) return false;                          // never accept when unconfigured
  const received = headers[name.toLowerCase()];       // case-insensitive lookup
  return Boolean(received) && safeEqual(received, secret); // WHOLE value, no "Bearer " parsing
}
  • The header name is whatever you typed in Dynatrace (DYNATRACE_WEBHOOK_HEADER, default Authorization). The expected value (DYNATRACE_WEBHOOK_SECRET) is the exact, whole header value, including any Bearer prefix you typed. Do not strip or parse the prefix.
  • Return 401 for a missing header or mismatch, 200 once handled.
  • Read the body raw (express.raw({ type: '*/*' })) so any content type works, and parse it only after the credential check.
  • A static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Use HTTPS and rotate the credential if it leaks.

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

Payload and Problem States

The payload is your template, so the shape below is an illustrative example, not a vendor schema. These examples assume this JSON template and dispatch on State:

{
  "ProblemID": "{ProblemID}",
  "State": "{State}",
  "ProblemTitle": "{ProblemTitle}",
  "ImpactedEntity": "{ImpactedEntity}"
}
StateMeaning
OPENA problem was opened (the only value Dynatrace's docs show, in the test-notification example)

A notification is also sent when a problem is resolved, but the docs don't show the {State} value it carries. The examples handle OPEN and log any other value; capture a real resolution (or check your Dynatrace environment) before matching on it. Include {State} in your template or you can't tell the two apart. The docs list no {ProblemURL} placeholder (their example has a literal "Problem URL": "https://example.com").

Environment Variables

DYNATRACE_WEBHOOK_HEADER=Authorization        # header name you added in Dynatrace
DYNATRACE_WEBHOOK_SECRET=your-secret-value    # exact, whole header value

Local Development

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

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

Use the printed URL as the webhook URL in Dynatrace.

Resources


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 9, 2026

View on GitHub →