Configure Incident outgoing webhooks
Incident outgoing webhooks allow Grafana IRM to send real-time incident updates to external systems. These webhooks can notify specified URLs when incidents are created, updated, or closed, enabling you to create custom workflows based on incident events.
About Incident outgoing webhooks
Outgoing webhooks send HTTP POST requests to your specified endpoints when incident events occur. You can use these webhooks to:
- Integrate incident data with external systems
- Trigger automated workflows based on incident events
- Customize incident response processes
- Build connections with other tools in your infrastructure
Note: Outgoing webhooks work well in conjunction with the Grafana IRM APIs.
Example use case
A common use case for outgoing webhooks is automating Jira issue creation:
Multiple teams at your organization use Grafana IRM, so you use labels to identify which incidents belong to which teams. Your current incident response workflow includes a manual step to create an issue in the related teams’ Jira project when an incident is declared.
To automate this process, you can configure an outgoing webhook to:
- Trigger when an incident is declared
- Read the incident event labels
- Use those labels to create an issue in the correct Jira project for the right team
Set up Incident outgoing webhooks
To install and configure the outgoing webhook integration:
- From the Grafana IRM Integrations tab, click Apps, and select Outgoing webhooks
- Click Install Integration
- Once installed, a signing secret is automatically generated for verifying webhook requests
Configure webhook triggers
After installation, you need to specify when the webhook should fire:
- Click Run when an event fires
- Enter a target endpoint URL for the outgoing webhook POST request
- Click Add event action to save your webhook configuration
Trigger webhooks based on events
You can configure webhooks to trigger on the following actions:
Event type | Description |
---|---|
Incident declared | Triggers when a new incident is created |
Incident change | Triggers when incident status or details are updated |
Incident closed | Triggers when an incident is resolved |
Incident matches a filter | Triggers when an incident matches specific criteria |
Available event types
Category | Event type |
---|---|
Incident is declared | grafana.incident.created |
Incident changes | grafana.incident.updated.role grafana.incident.updated.status grafana.incident.updated.title grafana.incident.updated.severity grafana.incident.added.label grafana.incident.removed.label |
Incident is resolved | grafana.incident.closed |
Define filters for event triggers
You can create specific filters to control when webhooks are triggered. Each filter condition uses key-value pairs with logical operators.
Supported filter conditions
Filter key | Possible values |
---|---|
status | active | resolved |
isdrill | true | false |
severity | critical | major | minor |
role | investigator | commander |
label | "<label-name>" (quotes optional) |
Logical operators
and()
: Combines conditions with logical AND (default behavior if no operator is specified)or()
: Combines conditions with logical OR-
: Negates a condition
Filter examples
-severity:critical
: Matches incidents with severity other than criticaland(label:customer severity:critical)
: Matches critical incidents with thecustomer
label(label:customer severity:critical)
: Simplified form of the above (AND is default)and(severity:critical or(label:"Customer A" label:"Customer B"))
: Matches critical incidents with eitherCustomer A
orCustomer B
label
Note: Event actions trigger at most once per incident. For example, if a
label:customer
filter is applied, adding, removing, and re-adding acustomer
label will result in only one webhook call.
Verify webhook requests
All webhook requests include a GI-Signature
header that you can use to verify the authenticity of the request. This signature contains a timestamp and HMAC-SHA256 signature.
Signature format
GI-Signature:t=1677589543,v1=12d6e3e06e66f2a32b4027827fbb95ce139ee8381a1cec1c40a02ec5f877797c
The v1
signature is calculated using HMAC-SHA256 with the following signing string:
signing-string = body-hash + ":" + timestamp + ":" + signature-version
Signature verification example
Given:
- Payload:
{ 'somejson': true }
- Secret:
some-secret-value
- Target URL:
https://myendpoint.com/some/path
- Timestamp:
1677589543
The signature is calculated as:
signature-version = "v1"
body-hash = "Zlr4UlirxgcHRLkhoMEI43NjQxMBWQSVYQ8ZGAABseM="
signing-string = "Zlr4UlirxgcHRLkhoMEI43NjQxMBWQSVYQ8ZGAABseM=:1677589543:v1"
hmac = a012b87c2e32680e8d028fd19b32f23f64f26f1632b6ff91dc17acd4214f27b3
GI-Signature:t=1677589543,v1=a012b87c2e32680e8d028fd19b32f23f64f26f1632b6ff91dc17acd4214f27b3
Command line verification
You can verify signatures using OpenSSL:
# Calculate the body hash
echo -n "{ 'somejson': true }" | openssl dgst -sha256 -binary | openssl enc -base64
Zlr4UlirxgcHRLkhoMEI43NjQxMBWQSVYQ8ZGAABseM=
# Calculate the HMAC signature
echo -n "Zlr4UlirxgcHRLkhoMEI43NjQxMBWQSVYQ8ZGAABseM=:1677589543:v1" | openssl dgst -sha256 -hmac "some-secret-value"
a012b87c2e32680e8d028fd19b32f23f64f26f1632b6ff91dc17acd4214f27b3
Sample outgoing webhook
Below is a sample webhook payload for an incident with an updated severity (grafana.incident.updated.severity
).
Request headers
The webhook includes the following headers:
Header | Value |
---|---|
gi-signature | t=1677589543,v1=12d6e3e06e66f2a32b4027827fbb95ce139ee8381a1cec1c40a02ec5f877797c |
content-type | application/json |
To conform with the CloudEvents specification, the following headers are also included:
Header | Value |
---|---|
ce-type | incident.webhook |
ce-time | 2023-03-02T14:12:00Z |
ce-subject | grafana.incident.updated.severity |
ce-specversion | 1.0 |
ce-source | /grafana/incident |
ce-id | webhook-out-6400aeb030670e95 |
ce-dataschema | v1.0.0 |
Webhook payload
The webhook payload is a JSON object with the following structure:
{
"version": "v1.0.0",
"id": "webhook-out-6400aeb030670e95",
"source": "/grafana/incident",
"time": "2023-03-02T14:12:00Z",
"event": "grafana.incident.updated.severity",
"incident": {
"incidentID": "5",
"severityID": 1,
"labels": [],
"isDrill": false,
"createdTime": "2023-02-27T15:06:25.243788Z",
"modifiedTime": "2023-03-02T14:12:00.730047Z",
"createdByUser": {
"userID": "grafana-incident:user-63f8b6204887f793",
"name": "admin",
"photoURL": "https://www.gravatar.com/avatar/46d229b033af06a191ff2267bca9ae56?s=512&d=retro"
},
"closedTime": "",
"durationSeconds": 860734,
"status": "active",
"title": "55",
"overviewURL": "/a/grafana-incident-app/incidents/5/55",
"roles": [
{
"role": "investigator",
"description": "Leads the investigation (has their full-time attention)",
"maxPeople": 1,
"mandatory": true,
"important": true,
"user": {
"userID": "grafana-incident:user-63f8b6204887f793",
"name": "admin",
"photoURL": "https://www.gravatar.com/avatar/46d229b033af06a191ff2267bca9ae56?s=512&d=retro"
}
},
{
"role": "observer",
"description": "Watching the incident",
"maxPeople": 0,
"mandatory": false,
"important": false,
"user": {
"userID": "grafana-incident:user-63f8b6204887f793",
"name": "admin",
"photoURL": "https://www.gravatar.com/avatar/46d229b033af06a191ff2267bca9ae56?s=512&d=retro"
}
},
{
"role": "commander",
"description": "Owns the incident (has their full-time attention)",
"maxPeople": 1,
"mandatory": true,
"important": true,
"user": {
"userID": "grafana-incident:user-63f8b6204887f793",
"name": "admin",
"photoURL": "https://www.gravatar.com/avatar/46d229b033af06a191ff2267bca9ae56?s=512&d=retro"
}
}
],
"taskList": {
"tasks": [
{
"taskID": "task-63ff1bf465deb38c",
"immutable": false,
"createdTime": "2023-03-01T09:33:40.759215968Z",
"modifiedTime": "2023-03-01T09:33:55.286168752Z",
"text": "111",
"status": "done",
"authorUser": {
"userID": "grafana-incident:user-63f8b6204887f793",
"name": "admin",
"photoURL": "https://www.gravatar.com/avatar/46d229b033af06a191ff2267bca9ae56?s=512&d=retro"
},
"assignedUser": {
"userID": "grafana-incident:user-63f8b6204887f793",
"name": "admin",
"photoURL": "https://www.gravatar.com/avatar/46d229b033af06a191ff2267bca9ae56?s=512&d=retro"
}
}
],
"todoCount": 0,
"doneCount": 1
},
"summary": "Resolved with no comment",
"heroImagePath": "/api/hero-images/default_org/mC0B9YIgrBH3Hf9jvnKsvalHT90QtlODeiXDd2aLgRsflEZrRHGS5ld2KfIAbndglMIHiKSR04FPRPBpS34DA182rpeBxF9MSypELoU7nyOzXS09YenaCUtBZEzCi1xd/v1128/5.png",
"incidentStart": "2023-02-20T15:06:26Z",
"incidentEnd": ""
}
}
For the complete API reference, see the OutgoingWebhookPayload documentation.