Skip to main content
Version: 1.4 (Current)

Custom Webhook Integration Examples

Overview​

Example webhook configurations for common monitoring tools. Each one is a body for POST /api/webhook_config and uses the syntax described in the Field Mapping Reference: paths into the payload, join, if_true / if_false, nested attributes, and fixed values in defaultValues.

Some things to keep in mind when adapting them:

  • Mappings copy values as they are. When a tool's status or priority is not a ToBeAlert severity (high, ALARM, triggered), the examples keep it in an attribute, give severity a default, and leave the translation to a policy — see Transforming values.
  • service and tags must be lists. A single string from the payload goes into an attribute instead, or the list is set in defaultValues.
  • Payload formats differ between tool versions and templates. Check a real payload in the webhook's payloadHistory before enabling the webhook.

Prometheus Alertmanager​

Incoming Data Format​

{
"receiver": "web.hook",
"status": "firing",
"alerts": [
{
"status": "firing",
"labels": {
"alertname": "HighMemoryUsage",
"instance": "10.0.1.100:9090",
"job": "prometheus",
"severity": "warning",
"team": "infrastructure"
},
"annotations": {
"summary": "High memory usage detected",
"description": "Memory usage is above 80%",
"dashboard": "https://grafana.example.com/d/memory",
"runbook": "https://wiki.example.com/runbooks/memory"
},
"startsAt": "2025-04-15T10:30:00Z",
"endsAt": "0001-01-01T00:00:00Z",
"generatorURL": "http://prometheus.example.com/graph"
}
],
"groupLabels": {
"alertname": "HighMemoryUsage"
},
"commonLabels": {
"alertname": "HighMemoryUsage",
"instance": "10.0.1.100:9090",
"job": "prometheus"
},
"commonAnnotations": {
"summary": "High memory usage detected"
}
}

Webhook Configuration​

arrayPath is alerts, so each Alertmanager alert becomes one ToBeAlert alert and every path is read inside that alert. commonLabels and commonAnnotations are outside the array and cannot be read; the same labels are taken from each alert.

{
"id": "prometheus-alertmanager",
"name": "Prometheus Alertmanager Integration",
"enabled": true,
"arrayPath": "alerts",
"fieldMappings": {
"resource": "labels.instance",
"event": "labels.alertname",
"severity": "labels.severity",
"text": "annotations.summary",
"group": "labels.team",
"attributes": {
"job": "labels.job",
"description": "annotations.description",
"dashboard_url": "annotations.dashboard",
"runbook": "annotations.runbook",
"alert_status": "status",
"firing_since": "startsAt",
"alert_url": "generatorURL"
}
},
"defaultValues": {
"environment": "Production",
"type": "prometheusAlert",
"origin": "prometheus",
"service": [
"prometheus"
]
}
}

Resulting Alert​

[
{
"resource": "10.0.1.100:9090",
"event": "HighMemoryUsage",
"severity": "warning",
"text": "High memory usage detected",
"group": "infrastructure",
"attributes": {
"job": "prometheus",
"description": "Memory usage is above 80%",
"dashboard_url": "https://grafana.example.com/d/memory",
"runbook": "https://wiki.example.com/runbooks/memory",
"alert_status": "firing",
"firing_since": "2025-04-15T10:30:00Z",
"alert_url": "http://prometheus.example.com/graph"
},
"environment": "Production",
"type": "prometheusAlert",
"origin": "prometheus",
"service": [
"prometheus"
]
}
]

Alertmanager also sends resolved notifications ("status": "resolved") with the same labels. They arrive with the same severity; to close or downgrade them, add a policy with condition attributes key alert_status Equals resolved and modifier severity set normal.

Datadog Webhooks​

Incoming Data Format​

The Datadog payload is a template you define in the Datadog webhook integration. This example assumes:

{
"id": "1234567890123456789",
"url": "https://app.datadoghq.com/monitors/12345",
"name": "High CPU on web-server",
"event": "CPU usage above threshold",
"priority": "high",
"host": "web-server-01",
"device": null,
"tags": [
"env:production",
"team:backend"
],
"metric": "system.cpu.total",
"value": 87.5,
"message": "CPU usage is 87.5% which is above the 80% threshold",
"alert_id": "123456789",
"alert_transition": "triggered",
"date": "2025-04-15T10:30:00Z",
"notification_url": "https://app.datadoghq.com/monitors/12345"
}

Webhook Configuration​

{
"id": "datadog-webhook",
"name": "Datadog Monitoring Integration",
"enabled": true,
"fieldMappings": {
"resource": "host",
"event": "name",
"text": "message",
"value": "value",
"tags": "tags",
"attributes": {
"priority": "priority",
"metric": "metric",
"monitor_url": "url",
"alert_transition": "alert_transition",
"datadog_alert_id": "alert_id"
}
},
"defaultValues": {
"environment": "Production",
"type": "datadogAlert",
"origin": "datadog",
"severity": "warning"
}
}

tags is copied as the list Datadog sends (env:production, team:backend). Datadog priority is kept in attributes.priority; severity defaults to warning. To raise it, add a policy with condition attributes key priority Equals high and modifier severity set critical.

Grafana Alerts​

Incoming Data Format​

{
"receiver": "grafana-webhook",
"status": "firing",
"alerts": [
{
"status": "firing",
"labels": {
"alertname": "GrafanaRule",
"dashboard": "Production Dashboard",
"panel": "CPU Usage",
"service": "web-service",
"severity": "critical"
},
"annotations": {
"description": "CPU usage is above 90%",
"summary": "High CPU alert",
"runbook": "https://wiki.example.com/runbooks/cpu"
},
"startsAt": "2025-04-15T10:30:00Z",
"endsAt": "0001-01-01T00:00:00Z",
"values": {
"B": 95.2,
"C": 90
}
}
],
"groupLabels": {},
"commonLabels": {
"alertname": "GrafanaRule",
"dashboard": "Production Dashboard"
},
"commonAnnotations": {
"summary": "High CPU alert"
}
}

Webhook Configuration​

{
"id": "grafana-alerts",
"name": "Grafana Alert Integration",
"enabled": true,
"arrayPath": "alerts",
"fieldMappings": {
"resource": "labels.service",
"event": "labels.alertname",
"severity": "labels.severity",
"text": "annotations.summary",
"value": "values.B",
"attributes": {
"dashboard": "labels.dashboard",
"panel": "labels.panel",
"description": "annotations.description",
"threshold": "values.C",
"runbook": "annotations.runbook",
"alert_status": "status"
}
},
"defaultValues": {
"environment": "Production",
"type": "grafanaAlert",
"origin": "grafana",
"group": "monitoring"
}
}

value receives the number in values.B (95.2) and attributes.threshold the number in values.C (90).

PagerDuty Webhooks​

Incoming Data Format​

{
"webhook": {
"id": "webhook-id",
"summary": "Critical: Database connection failed",
"timestamp": "2025-04-15T10:30:00Z",
"incident": {
"id": "P123456",
"incident_number": 12345,
"title": "Database connection failed",
"description": "Unable to connect to primary database",
"status": "triggered",
"urgency": "high",
"service": {
"id": "PABCDEF",
"name": "Database Service"
},
"assignments": [
{
"assignee": {
"summary": "John Doe"
}
}
]
}
}
}

Webhook Configuration​

{
"id": "pagerduty-webhook",
"name": "PagerDuty Integration",
"enabled": true,
"fieldMappings": {
"resource": "webhook.incident.service.name",
"event": "webhook.incident.title",
"text": "webhook.incident.description",
"attributes": {
"incident_id": "webhook.incident.id",
"incident_number": "webhook.incident.incident_number",
"urgency": "webhook.incident.urgency",
"incident_status": "webhook.incident.status",
"assigned_to": "webhook.incident.assignments[0].assignee.summary"
}
},
"defaultValues": {
"environment": "Production",
"type": "pagerdutyIncident",
"origin": "pagerduty",
"severity": "major",
"group": "operations",
"attributes": {
"assigned_to": "Unassigned"
}
}
}

assigned_to takes the first assignee; when the incident has no assignments, the default Unassigned from defaultValues.attributes is used. The PagerDuty urgency stays in an attribute; a policy on attributes key urgency Equals high can set severity to critical.

Custom Application Monitoring​

Incoming Data Format​

{
"application": "payment-service",
"version": "2.1.0",
"environment": "Production",
"instance": "payment-02",
"error": {
"type": "DatabaseException",
"message": "Connection timeout to database",
"stack_trace": "...",
"count": 15
},
"metrics": {
"active_connections": 150,
"failed_requests": 25,
"response_time": 2500
},
"context": {
"user_impacted": true,
"affected_transactions": [
"payment",
"refund"
],
"recovery_action": "restart_database_pool"
},
"timestamp": "2025-04-15T10:30:00Z",
"links": {
"logs": "https://logs.example.com/search?q=payment-service",
"dashboard": "https://grafana.example.com/d/payment-service",
"trace": "https://trace.example.com/trace/abc123"
}
}

Webhook Configuration​

{
"id": "payment-service-monitoring",
"name": "Payment Service Monitoring",
"enabled": true,
"fieldMappings": {
"resource": "instance",
"event": "error.type",
"environment": "environment",
"text": "error.message",
"value": "error.count",
"tags": "context.affected_transactions",
"attributes": {
"application": "application",
"version": "version",
"stack_trace": "error.stack_trace",
"active_connections": "metrics.active_connections",
"response_time_ms": "metrics.response_time",
"user_impact": {
"path": "context.user_impacted",
"if_true": "customers affected",
"if_false": "internal only"
},
"affected_transactions": {
"path": "context.affected_transactions",
"join": ", "
},
"recovery_action": "context.recovery_action",
"logs_url": "links.logs",
"dashboard_url": "links.dashboard",
"trace_url": "links.trace"
}
},
"defaultValues": {
"type": "applicationError",
"origin": "payment-service",
"severity": "minor",
"group": "payments",
"service": [
"payments"
]
}
}

This example uses:

  • if_true / if_false to turn the boolean context.user_impacted into readable text
  • join to store context.affected_transactions as one string attribute, while tags keeps the same array as a list
  • environment read from the payload (no default)

Resulting Alert​

[
{
"resource": "payment-02",
"event": "DatabaseException",
"environment": "Production",
"text": "Connection timeout to database",
"value": 15,
"tags": [
"payment",
"refund"
],
"attributes": {
"application": "payment-service",
"version": "2.1.0",
"stack_trace": "...",
"active_connections": 150,
"response_time_ms": 2500,
"user_impact": "customers affected",
"affected_transactions": "payment, refund",
"recovery_action": "restart_database_pool",
"logs_url": "https://logs.example.com/search?q=payment-service",
"dashboard_url": "https://grafana.example.com/d/payment-service",
"trace_url": "https://trace.example.com/trace/abc123"
},
"type": "applicationError",
"origin": "payment-service",
"severity": "minor",
"group": "payments",
"service": [
"payments"
]
}
]

To set severity from the error count, add policies such as condition value Greater than 20 → severity set critical and value Greater than 10 → severity set major (see Numeric comparisons on text values).

AWS CloudWatch Alerts​

Incoming Data Format​

{
"AlarmName": "CPU-Utilization-High",
"AlarmDescription": "CPU utilization exceeds 80%",
"AWSAccountId": "123456789012",
"NewStateValue": "ALARM",
"NewStateReason": "Threshold Crossed",
"StateChangeTime": "2025-04-15T10:30:00Z",
"Region": "US West (Oregon)",
"Dimensions": {
"InstanceId": "i-1234567890abcdef0",
"InstanceType": "t3.medium"
},
"Metric": {
"Name": "CPUUtilization",
"Namespace": "AWS/EC2",
"Value": 87.5,
"Unit": "Percent"
},
"Trigger": {
"Threshold": 80,
"ComparisonOperator": "GreaterThanThreshold"
}
}

Webhook Configuration​

{
"id": "aws-cloudwatch",
"name": "AWS CloudWatch Integration",
"enabled": true,
"fieldMappings": {
"resource": "Dimensions.InstanceId",
"event": "AlarmName",
"text": "AlarmDescription",
"value": "Metric.Value",
"attributes": {
"state": "NewStateValue",
"state_reason": "NewStateReason",
"metric": "Metric.Name",
"namespace": "Metric.Namespace",
"unit": "Metric.Unit",
"threshold": "Trigger.Threshold",
"instance_type": "Dimensions.InstanceType",
"region": "Region",
"aws_account": "AWSAccountId"
}
},
"defaultValues": {
"environment": "Production",
"type": "cloudwatchAlarm",
"origin": "aws-cloudwatch",
"severity": "warning",
"group": "cloud-infrastructure",
"service": [
"aws"
]
}
}

The CloudWatch state (ALARM, OK, INSUFFICIENT_DATA) is kept in attributes.state. Translate it with policies: attributes key state Equals ALARM → severity set critical, and OK → normal. Console links are not built by the mapping; if you need them, send them in the payload (for example from an SNS → Lambda formatter) and map the field.

Kubernetes Monitoring​

Incoming Data Format​

{
"namespace": "production",
"pod": "web-service-7d4f8c9b5-abc123",
"container": "web-service",
"node": "k8s-worker-01",
"cluster": "prod-cluster-01",
"alert": {
"name": "PodCrashLooping",
"message": "Pod is in crash loop backoff",
"severity": "critical",
"restart_count": 15
},
"labels": {
"app": "web-service",
"version": "v2.1.0",
"team": "backend"
},
"annotations": {
"description": "Pod has restarted 15 times in the last hour",
"runbook": "https://wiki.example.com/k8s/pod-crash-loop"
},
"timestamp": "2025-04-15T10:30:00Z"
}

Webhook Configuration​

{
"id": "kubernetes-monitoring",
"name": "Kubernetes Monitoring Integration",
"enabled": true,
"fieldMappings": {
"resource": "pod",
"event": "alert.name",
"environment": "namespace",
"severity": "alert.severity",
"text": "alert.message",
"value": "alert.restart_count",
"group": "labels.team",
"resourceParent": "node",
"attributes": {
"app": "labels.app",
"container": "container",
"cluster": "cluster",
"version": "labels.version",
"description": "annotations.description",
"runbook": "annotations.runbook"
}
},
"defaultValues": {
"type": "kubernetesAlert",
"origin": "kubernetes",
"service": [
"kubernetes"
]
}
}

environment is the namespace as sent (production) and resourceParent places the pod under its node in the resource graph.

Testing Your Integration​

Test Command​

# Send a sample payload (add auth headers when the webhook requires them)
curl -X POST https://your-tobealert.com:9000/api/webhooks/custom/your-webhook-id \
-H "Content-Type: application/json" \
-d @sample-payload.json

A successful call returns 200 with alerts_created and the id, resource, event, and severity of each alert. When some alerts fail, the response lists each failure in errors with the mapped data and the reason.

Verify the Result​

Check the created alert in ToBeAlert to ensure:

  • Required fields have the values you expect (and not the defaults, unless that is intended)
  • service and tags are lists
  • Attributes hold the payload values you mapped
  • Severity is a ToBeAlert severity, or a policy translates it

Tips for Success​

  1. Start disabled — create the webhook without enabled: true, point the tool at it, and build the mapping from the payloads stored in payloadHistory
  2. Use real data — vendor payloads change with versions and templates
  3. Keep source values in attributes — they are what policies use to translate statuses and priorities
  4. Check errorHistory — every rejected or failed delivery is recorded with its reason