---
title: "Outgoing webhooks for Grafana IRM | Grafana Cloud documentation"
description: "Configure and use outgoing webhooks in Grafana IRM"
---

# Outgoing webhooks for Grafana IRM

> Note
> 
> Grafana IRM outgoing webhooks are now managed from a unified interface and processed through a shared backend service. If you have existing outgoing webhooks configured through the legacy Incident outgoing webhooks integration, those webhooks remain fully functional. However, we recommend migrating to the shared IRM webhook experience to take advantage of the latest features and ensure long-term support. For more information, refer to the [Migrate from Incident webhooks](#migrate-from-incident-outgoing-webhooks) section of this document.

Outgoing webhooks in Grafana IRM enable flexible integration with external systems by automatically sending event data related to alerts and incidents to your preferred tools and APIs.

## Webhook presets

Webhook presets provide pre-configured integrations that allow you to quickly set up and customize webhooks to automate actions in your IRM workflow. Each preset is designed for specific use cases and includes optimized default settings that you can further customize based on your requirements.

### Available webhook presets

- **Simple webhook for alert groups**: Sends basic alert group data with minimal configuration.
  
  Ideal for simple integrations and use in escalation steps where you need straightforward event notifications.
- **Advanced webhook for alert groups**: Provides full customization capabilities including templating, conditional execution, and advanced filtering.
  
  Use this preset when you need fine-grained control over webhook behavior and payload formatting.
- **Advanced webhook for incidents**: Offers comprehensive incident data with customizable settings and templating support.
  
  Perfect for integrating with external systems that are part of your incident management process or creating custom incident workflows.
- **Grafana Assistant for IRM**: Forwards alert group or incident data to Grafana Assistant for automated analysis and investigation.
  
  Use this preset to trigger a [Grafana Assistant investigation](/docs/grafana-cloud/machine-learning/assistant/introduction/investigations/) when an alert group or incident event occurs. Grafana Assistant coordinates multiple specialist agents to analyze incidents in parallel and posts findings to your timeline.
- **Schedule webhook**: Responds to on-call schedule events such as shift changes, rotation updates, and shift swaps.
  
  Use this preset to integrate schedule lifecycle events with external systems or custom tooling. Schedule webhooks can be filtered to specific schedules. For more details, refer to [Schedule webhooks](#schedule-webhooks).
- **Grafana Sift for alert groups**: Forwards alert group data to Grafana Sift for infrastructure telemetry analysis.
  
  Use this preset to trigger a [Sift investigation](/docs/grafana-cloud/machine-learning/sift/) when an alert group event occurs. Sift is a free diagnostic assistant that performs infrastructure telemetry investigations, running checks and curating investigative summaries. Investigation results are posted to your alert group timeline as resolution notes.

## Configure an outgoing webhook

To create a webhook from the IRM UI:

1. In Grafana Cloud, go to **Alerts &amp; IRM &gt; IRM &gt; Integrations**.
2. Select the **Outgoing Webhooks** tab.
3. Click **+ Create an Outgoing Webhook**.
4. Select the preset that applies for your configuration:
   
   - **Simple webhook for alert groups** – Sends basic alert group data (used for escalation steps).
   - **Advanced webhook for alert groups** – Customizable with additional settings and templating.
   - **Advanced webhook for incidents** – Customizable with additional settings and templating.
   - **Schedule webhook** – Responds to on-call schedule events.
   - **Grafana Assistant for IRM** – Forwards data to Grafana Assistant for automated analysis.
   - **Grafana Sift for alert groups** – Forwards alert group data to Grafana Sift.
5. Complete the webhook configuration form.
6. Click **Create** to save the webhook.

For information about configuring outgoing webhooks via Terraform, refer to the [Terraform documentation](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/oncall_outgoing_webhook).

### Webhook configuration fields

The following fields are available when configuring an outgoing webhook:

Expand table

| Field                     | Description                                                             | Required                   |
|---------------------------|-------------------------------------------------------------------------|----------------------------|
| **Name**                  | A descriptive display name                                              | Yes                        |
| **Enabled**               | Whether the webhook is active                                           | Yes (default: true)        |
| **Assign to team**        | Team that owns or manages the webhook                                   | No                         |
| **Trigger type**          | Event that causes the webhook to execute                                | Yes                        |
| **HTTP method**           | GET, POST, PUT, PATCH, DELETE, or OPTIONS                               | Yes (unless preconfigured) |
| **Integrations**          | Restrict execution to specific integrations                             | No                         |
| **Labels**                | Labels to include in the payload body                                   | No                         |
| **Webhook URL**           | Destination for the request                                             | Yes (unless preconfigured) |
| **Headers**               | Optional request headers (templating supported)                         | No                         |
| **Username**              | HTTP Basic Auth username                                                | No                         |
| **Password**              | HTTP Basic Auth password                                                | No                         |
| **Authorization**         | Supports basic auth or custom headers                                   | No                         |
| **Trigger template**      | Used to conditionally execute the webhook                               | No                         |
| **Forward whole payload** | Sends the full event object as received by IRM instead of a custom body | No                         |

> Note
> 
> Your destination endpoints must respond within a 4-second timeout window.

## Supported triggers

The following event types are available to trigger a webhook to execute.

### Alert group events

Expand table

| Event                     | Description                                          |
|---------------------------|------------------------------------------------------|
| Manual or escalation step | Triggered manually or as part of an escalation chain |
| Alert group created       | A new alert group is created                         |
| Acknowledged              | The alert group was acknowledged                     |
| Resolved                  | The alert group was resolved                         |
| Silenced                  | The alert group was silenced                         |
| Unsilenced                | The alert group was unsilenced                       |
| Unresolved                | The alert group was reopened                         |
| Unacknowledged            | Acknowledgment was removed                           |
| Status change             | Any state change event                               |
| Resolution note added     | A resolution note was added                          |
| Personal notification     | Triggered by a personal notification rule            |

### Schedule events

Expand table

| Event              | Description                                          |
|--------------------|------------------------------------------------------|
| On-call Changed    | The set of on-call users for a schedule changes      |
| Shift Started      | A user’s on-call shift begins                        |
| Shift Ended        | A user’s on-call shift ends                          |
| Going On-call      | A user is about to go on-call (advance notification) |
| Shift Swap Created | A shift swap request is created                      |
| Shift Swap Taken   | A shift swap request is accepted by another user     |

### Incident events

Expand table

| Event                | Description                                                       |
|----------------------|-------------------------------------------------------------------|
| Incident declared    | A new incident is declared                                        |
| Incident changed     | Updates to title, severity, status, role, or labels               |
| Incident resolved    | The incident is resolved                                          |
| Manual from incident | Trigged manually via dropdown in incident Activity-&gt;Action Tab |

> Note
> 
> Each matching event triggers a webhook once. Removing and re-adding a matching label won’t retrigger the webhook.

#### Incident subevents

Expand table

| Trigger              | Subevent                                                                                                                                                                                                                                  |
|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Incident declared    | `grafana.incident.created`                                                                                                                                                                                                                |
| Incident changed     | `grafana.incident.updated.role`  <br />`grafana.incident.updated.status`  <br />`grafana.incident.updated.title`  <br />`grafana.incident.updated.severity`  <br />`grafana.incident.added.label`  <br />`grafana.incident.removed.label` |
| Incident resolved    | `grafana.incident.closed`                                                                                                                                                                                                                 |
| Manual from incident | `grafana.incident.manual`                                                                                                                                                                                                                 |

## Schedule webhooks

Schedule webhooks are a dedicated webhook type for responding to on-call schedule events. They use a separate preset with schedule-specific trigger types and template variables, and can be filtered to specific schedules.

### Creating a schedule webhook

To create a schedule webhook, navigate to **Outgoing Webhooks**, click **+ Create**, and select the **Schedule webhook** preset.

### Schedule filtering

By default a schedule webhook fires for all schedules. To restrict it to specific schedules, use the **Schedules** filter field. When one or more schedules are selected, the webhook only fires for events from those schedules.

### Schedule webhook template variables

Schedule webhooks receive a different set of template variables than alert-group webhooks. The available variables depend on the trigger type.

Available template fields for schedule events

#### Common fields

All schedule webhook payloads include:

- `{{ event.type }}` - Type of schedule event (e.g. `shift started`, `on-call changed`)
- `{{ event.time }}` - ISO 8601 timestamp of the event
- `{{ schedule.id }}` - UID of the schedule
- `{{ schedule.name }}` - Name of the schedule
- `{{ schedule.team.id }}` - UID of the schedule’s team (null if no team)
- `{{ schedule.team.name }}` - Name of the schedule’s team
- `{{ webhook.id }}` - UID of the webhook
- `{{ webhook.name }}` - Name of the webhook

#### Shift Started / Shift Ended

- `{{ user.user_id }}` - UID of the user starting or ending the shift
- `{{ user.username }}` - Username of the user
- `{{ user.email }}` - Email of the user

#### On-call Changed

- `{{ previous_on_call }}` - Array of users previously on-call, each with `user_id`, `username`, `email`
- `{{ current_on_call }}` - Array of users currently on-call
- `{{ users_added }}` - Array of users added to on-call
- `{{ users_removed }}` - Array of users removed from on-call

#### Going On-call

- `{{ user.user_id }}` - UID of the user about to go on-call
- `{{ user.username }}` - Username of the user
- `{{ user.email }}` - Email of the user
- `{{ shift.start }}` - ISO 8601 start time of the upcoming shift
- `{{ shift.end }}` - ISO 8601 end time of the upcoming shift

#### Shift Swap Created / Shift Swap Taken

- `{{ shift_swap_request.id }}` - UID of the shift swap request
- `{{ shift_swap_request.beneficiary }}` - User requesting the swap (`user_id`, `username`, `email`)
- `{{ shift_swap_request.benefactor }}` - User accepting the swap (null if not yet taken)
- `{{ shift_swap_request.swap_start }}` - ISO 8601 start time of the swap period
- `{{ shift_swap_request.swap_end }}` - ISO 8601 end time of the swap period
- `{{ shift_swap_request.description }}` - Description of the swap request

### Schedule webhook payload example

The following is an example payload for a **Shift Started** event:

JSON ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```json
{
  "event": {
    "type": "shift started",
    "time": "2026-03-20T09:00:00+00:00"
  },
  "schedule": {
    "id": "SCHED123ABC",
    "name": "Primary On-Call",
    "team": {
      "id": "TEAM456DEF",
      "name": "Platform Engineering"
    }
  },
  "user": {
    "user_id": "USER789GHI",
    "username": "alice",
    "email": "alice@example.com"
  },
  "webhook": {
    "id": "WH9NSKXWPXSNY3",
    "name": "Schedule Sync"
  }
}
```

## Use webhook templates

Use Jinja2 templates to include dynamic content from the event context. Templates have access to context data from the triggering event. Supported fields vary by trigger type.

For more information about templates in IRM, refer to the [Templates documentation](/docs/grafana-cloud/alerting-and-irm/irm/configure/escalation-routing/alert-templates/#configure-alert-templates).

### Common template fields

- `{{ event.type }}` – Type of event
- `{{ event.time }}` – Timestamp
- `{{ user.username }}` – Username if triggered by a user
- `{{ alert_group.title }}` – Alert group title
- `{{ alert_payload }}` – Contents of the first alert in the group
- `{{ incident.title }}` – Incident title
- `{{ incident.severity }}` – Incident severity
- `{{ webhook.name }}` – Webhook name

Available template fields for alert group events

### Available template fields for alert groups

The following fields are available to templates when a webhook executes:

#### Event information

- `{{ event.type }}` - Type of event that triggered the webhook
- `{{ event.time }}` - Timestamp when the event occurred
- `{{ event.user.* }}` - Context data as provided by the user for [Personal Notification webhooks](/docs/grafana-cloud/alerting-and-irm/irm/notify-responders/notification-channels/#configure-webhook-notifications)

#### User information

Available when the event was triggered by a user action:

- `{{ user.id }}` - User ID
- `{{ user.username }}` - Username
- `{{ user.email }}` - Email address

#### Alert group information

- `{{ alert_group.id }}` - Alert group ID
- `{{ alert_group.integration_id }}` - Integration ID
- `{{ alert_group.route_id }}` - Route ID
- `{{ alert_group.alerts_count }}` - Number of alerts in the group
- `{{ alert_group.state }}` - Current state
- `{{ alert_group.created_at }}` - Creation timestamp
- `{{ alert_group.resolved_at }}` - Resolution timestamp
- `{{ alert_group.acknowledged_at }}` - Acknowledgment timestamp
- `{{ alert_group.title }}` - Alert group title
- `{{ alert_group.permalinks }}` - Links to the alert group
- `{{ alert_group.labels }}` - Alert group labels
- `{{ alert_group.resolution_notes }}` - Alert group resolution notes

#### Alert information

- `{{ alert_payload }}` - Content of the first alert in the group

#### Integration information

- `{{ integration.id }}` - Integration ID
- `{{ integration.type }}` - Integration type
- `{{ integration.name }}` - Integration name
- `{{ integration.team }}` - Team the integration belongs to
- `{{ integration.labels }}` - Integration labels

#### User action information

- `{{ alert_group_acknowledged_by }}` - User who acknowledged the alert
- `{{ alert_group_resolved_by }}` - User who resolved the alert

#### Notification information

- `{{ notified_users }}` - Array of users who received notifications
- `{{ users_to_notify }}` - Array of users who will be notified next

#### Webhook information

- `{{ webhook.id }}` - Webhook ID
- `{{ webhook.name }}` - Webhook name
- `{{ webhook.labels }}` - Webhook labels

#### Previous webhook responses

- `{{ responses }}` - Responses from other webhooks for this alert group

Available template fields for incident events

### Available template fields for incidents

The following fields are available to templates when a webhook executes:

#### Event information

- `{{ event.type }}` - Type of event that triggered the webhook
- `{{ event.event }}` - Specific incident event (e.g. `grafana.incident.updated.title`)
- `{{ event.time }}` - Timestamp when the event occurred

#### Incident information

- `{{ incident.incidentID }}` - Incident ID
- `{{ incident.title }}` - Title of the incident
- `{{ incident.summary }}` - Summary of the incident
- `{{ incident.status }}` - Status of the incident
- `{{ incident.severity }}` - Severity of the incident
- `{{ incident.labels }}` - Incident labels
- `{{ incident.incidentStart }}` - Incident start timestamp
- `{{ incident.incidentEnd }}` - Incident end timestamp

For a detailed list of all the available fields refer to the [Incident API reference documentation](/docs/grafana-cloud/alerting-and-irm/irm/reference/incident-api/reference/#getincidentresponse).

#### Webhook information

- `{{ webhook.id }}` - Webhook ID
- `{{ webhook.name }}` - Webhook name
- `{{ webhook.labels }}` - Webhook labels

#### Previous webhook responses

- `{{ responses }}` - Responses from other webhooks for this incident

### Example templates

Basic JSON payload:

JSON ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```json
{
  "name": "{{ alert_payload.labels.alertname }}",
  "message": "{{ alert_payload.annotations.description }}"
}
```

URL with query params:

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```none
https://example.com/tickets?assignee={{ user.email }}
```

Use `tojson()` to format objects:

JSON ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```json
{
  "labels": {{ alert_payload.labels | tojson() }}
}
```

### Reference previous responses

You can access results from previously executed webhooks using the `{{ responses }}` variable. This enables advanced workflows, such as updating a ticket that was created by an earlier webhook.

> Note
> 
> There is a retention policy of 90 days for previous responses.

### Conditional execution

Use the **Trigger Template** field to control when a webhook executes. The webhook will run only if the template evaluates to an empty string, `True`, or `1`.

Example to trigger only for high-severity alerts:

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```none
{% if alert_payload.labels.severity == "high" %}true{% endif %}
```

Example to trigger only for incidents with “Critical” severity and the “Customer” label set:

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```none
{% if incident.severity == "Critical" and incident.labels | selectattr('key', 'equalto', 'Customer') | list | length > 0 %}true{% endif %}
```

## View webhook execution results

You can view webhook execution history in the **Outgoing Webhooks** tab. The list includes the latest events and associated data.

Click a webhook to view detailed execution information:

- The triggered event and context
- Request details: URL, headers, and body
- Response code and response body
- Template evaluation output

You can also find webhook responses associated with specific events:

- For **alert group webhooks**, a link to the corresponding response appears in the **alert group timeline**, accessible from the alert group detail page.
- For **incident webhooks**, execution results appear in the **incident timeline** under the **All activity** view.

## Retry policy

If a webhook request fails, IRM retries the request up to three times with a one-second interval between attempts. IRM only retries requests if there is a timeout exception in the process (e.g. connection timeouts or read timeouts).

## Migrate from Incident outgoing webhooks

Legacy incident webhooks continue to work but will eventually be deprecated in future releases.

To migrate a webhook from the legacy Incident outgoing webhooks app, manually recreate the webhook in the shared IRM Outgoing Webhooks interface with the following settings:

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```none
Name: <your webhook name>
HTTP method: POST
URL: <your URL>
Trigger type: <your original trigger type>
Customize forwarded data [x]
Data template: {{ incident }}
```

Be aware that the IRM shared webhook requests do not include signature or Cloud Events headers. Also, legacy incident webhooks retried on some `5xx` errors while shared webhooks will not (there will be log records though).

After enabling the corresponding IRM webhook, test your new webhook before removing the legacy webhook. Once verified, delete the legacy configuration to avoid duplicate executions.

If your webhook previously used the **Incident matches filters** trigger, use the **Incident changed** trigger type. If you want to respond to other incident events, such as declarations or resolutions, create additional webhooks for those trigger types as needed.

Recreate your filter logic using Jinja templating in the **Trigger template** field. This provides equivalent behavior to the original filtered trigger in the legacy Incident integration.

For example:

`-severity:critical` is equivalent to `{{ incident.severity != "critical" }}`

or

`and(label:customer severity:critical)` can be expressed as `{{ incident.severity == "Critical" and incident.labels | selectattr('key', 'equalto', 'Customer') | list | length > 0 }}`

## Examples and integrations

Outgoing webhooks work well in conjunction with the [IRM API](/docs/grafana-cloud/alerting-and-irm/irm/reference/#api-reference-guides).

For example webhook configurations with common integrations, refer to:

- [JIRA integration](/docs/grafana-cloud/alerting-and-irm/irm/integrations/alert-sources/jira/#configure-jira-to-send-alerts-to-grafana-irm)
- [ServiceNow integration](/docs/grafana-cloud/alerting-and-irm/irm/integrations/alert-sources/servicenow/#create-integration)
- [Zendesk integration](/docs/grafana-cloud/alerting-and-irm/irm/integrations/alert-sources/zendesk/#configure-zendesk-to-send-alerts-to-grafana-irm)
