Home
On-call

Dynatrace

Dynatrace delivers to BatonDeck through a problem notification with a custom payload.

Dynatrace delivers to BatonDeck through a problem notification with a custom payload.

  • Auth: api_key — Dynatrace cannot compute the BatonDeck HMAC, but it can send a custom header.
  • Endpoint: POST https://<your-oncall-host>/i/<integrationId>
  • Header: x-batondeck-key: <your key>
  • One problem notification = one incident ticket.

1. Create the integration

create_integration {
  projectId, name: "prod-dynatrace", source: "dynatrace", boardId: "B-…",
  auth: { mode: "api_key", apiKey: "<a long random value you generate>" },
  routing: { mode: "oncall", onCallAgent: "claude-oncall" },
  mapping: {
    severityMap: {
      availability: "urgent",
      error: "urgent",
      performance: "high",
      resource_contention: "high",
      monitoring_unavailable: "high",
      custom_alert: "normal"
    }
  }
}

Set severityMap. Dynatrace's {ProblemSeverity} renders its own vocabulary — AVAILABILITY, PERFORMANCE, RESOURCE_CONTENTION, CUSTOM_ALERT, MONITORING_UNAVAILABLE — and only ERROR overlaps with BatonDeck's built-in severity words. Everything else falls through to priority normal, so a total availability outage arrives at the same priority as a warning unless you map it.

2. Add the problem notification

Settings → Integration → Problem notifications → Set up notifications → Custom integration.

FieldValue
Webhook URLhttps://<your-oncall-host>/i/ing_0123456789abcdef0123456789abcdef
Additional HTTP headersname x-batondeck-key, value your key (mark it a secret)
Custom payloadthe template below
Call webhook if new events merge into existing problemsyour choice — see Lifecycle below

3. Custom payload template

Paste this verbatim. Every field name is one BatonDeck reads.

{
  "problemId": "{PID}",
  "state": "{State}",
  "problemTitle": "{ProblemTitle}",
  "severityLevel": "{ProblemSeverity}",
  "problemImpact": "{ProblemImpact}",
  "problemUrl": "{ProblemURL}",
  "problemDetailsText": "{ProblemDetailsText}",
  "impactedEntities": {ImpactedEntities}
}

The one thing to get right: {ImpactedEntities} is NOT quoted. It renders a JSON array, and BatonDeck reads it only when it arrives as an array. Wrap it in quotes and it becomes a string — which is not an error, produces no warning, and silently drops every impacted entity name from the ticket. Every other placeholder in the template is quoted, which is exactly what makes this one easy to miss.

BatonDeck also accepts Dynatrace's default placeholder names case-insensitively — PID, State, ProblemTitle, ProblemSeverity, ProblemURL, ProblemDetailsText, ProblemImpact, ImpactedEntities — so an existing template built from those names works without renaming anything.

problemId is required. A payload without {PID} (or ProblemID) is refused with 400 unrecognized_payload, because it is the correlation key: without it, every notification about one problem would open a new ticket.

No timestamp field. The template sends none, so occurredAt is the moment BatonDeck receives the delivery — within seconds of the notification for a problem notification. If you add one, it must be an ISO 8601 string; an epoch-millisecond value falls back to receipt time silently.

4. What lands on the ticket

Ticket fieldComes from
Correlation keyproblemId / PID
Firing / resolvedstateRESOLVED or CLOSED resolves; anything else (including OPEN) fires
SeverityseverityLevel / ProblemSeverity, lowercased; defaults to warning
TitleproblemTitle, else "Dynatrace problem"
DescriptionproblemDetailsText
LinksproblemUrl
Annotation dynatrace_statethe uppercased state
Annotation dynatrace_impactproblemImpact
Annotation impacted_entitiesthe name of each entry in impactedEntities, comma-joined

Lifecycle

With the default correlate lifecycle, repeat notifications about the same problemId bump the occurrence count on the open ticket, and a RESOLVED notification annotates it and leaves it open for the agent to close. Switch to autoclose if you want an untouched ticket cancelled when Dynatrace closes the problem — it will never yank a ticket an agent has already claimed.

When nothing arrives

Delivery log reasonWhat it means
No rows at allDynatrace never reached the function — use the notification's Send test notification button, which posts a real request through the whole path.
api_key_mismatchThe header name or value differs. api_key mode reads only x-batondeck-key; an Authorization header is consulted only in jwt mode.
400 unrecognized_payloadThe detail names the problem. Missing problemId/PID is the common one.
400 invalid_jsonUsually {ProblemDetailsText} rendering multi-line text inside a JSON string. Drop that line, re-test, then decide whether you need it.
404 from the endpointWrong integration id, or the integration is disabled. Both answer identically on purpose.

Next: On-call ingestion overview · Datadog