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, giveseveritya default, and leave the translation to a policy — see Transforming values. serviceandtagsmust be lists. A single string from the payload goes into an attribute instead, or the list is set indefaultValues.- Payload formats differ between tool versions and templates. Check a real payload in the webhook's
payloadHistorybefore 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_falseto turn the booleancontext.user_impactedinto readable textjointo storecontext.affected_transactionsas one string attribute, whiletagskeeps the same array as a listenvironmentread 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)
serviceandtagsare lists- Attributes hold the payload values you mapped
- Severity is a ToBeAlert severity, or a policy translates it
Tips for Success
- Start disabled — create the webhook without
enabled: true, point the tool at it, and build the mapping from the payloads stored inpayloadHistory - Use real data — vendor payloads change with versions and templates
- Keep source values in attributes — they are what policies use to translate statuses and priorities
- Check
errorHistory— every rejected or failed delivery is recorded with its reason