> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devhelm.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Alert Routing by Tag

> Route DevHelm alerts to different teams based on monitor tags and notification policies

By the end of this guide, you'll have monitors tagged by team or service, with notification policies that route each group's alerts to the right channels.

<Accordion title="Prerequisites">
  * At least two alert channels — see [Alerting guide](/guides/alerting)
  * Multiple monitors — see [Monitors guide](/guides/monitors)
</Accordion>

For conceptual background, see [Notification policies](/alerting/notification-policies).

## Strategy

Tag your monitors by team, service, or environment. Then create notification policies with `monitor_tag_in` match rules that route alerts to team-specific channels.

## Set up tag-based routing

<Steps>
  <Step title="Tag your monitors">
    <CodeGroup>
      ```yaml devhelm.yml theme={null}
      tags:
        - name: payments
          color: "#8b5cf6"
        - name: auth
          color: "#3b82f6"
        - name: infrastructure
          color: "#10b981"

      monitors:
        - name: Stripe Webhook
          type: HTTP
          config:
            url: https://api.example.com/webhooks/stripe/health
            method: GET
          frequencySeconds: 60
          regions: [us-east, eu-west]
          tags: [payments]

        - name: Auth API
          type: HTTP
          config:
            url: https://auth.example.com/health
            method: GET
          frequencySeconds: 60
          regions: [us-east, eu-west]
          tags: [auth]

        - name: Database
          type: TCP
          config:
            host: db.example.com
            port: 5432
          frequencySeconds: 60
          regions: [us-east]
          tags: [infrastructure]
      ```
    </CodeGroup>
  </Step>

  <Step title="Create team-specific policies">
    ```bash theme={null}
    curl -X POST https://api.devhelm.io/api/v1/notification-policies \
      -H "Authorization: Bearer $DEVHELM_API_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Payments team",
        "priority": 10,
        "matchRules": [
          { "type": "monitor_tag_in", "values": ["payments"] }
        ],
        "escalation": {
          "steps": [{
            "delayMinutes": 0,
            "channelIds": ["<payments-slack-id>"]
          }]
        }
      }'

    curl -X POST https://api.devhelm.io/api/v1/notification-policies \
      -H "Authorization: Bearer $DEVHELM_API_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Auth team",
        "priority": 10,
        "matchRules": [
          { "type": "monitor_tag_in", "values": ["auth"] }
        ],
        "escalation": {
          "steps": [{
            "delayMinutes": 0,
            "channelIds": ["<auth-slack-id>"]
          }]
        }
      }'

    curl -X POST https://api.devhelm.io/api/v1/notification-policies \
      -H "Authorization: Bearer $DEVHELM_API_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Infrastructure (catch-all)",
        "priority": 0,
        "matchRules": [],
        "escalation": {
          "steps": [{
            "delayMinutes": 0,
            "channelIds": ["<infra-slack-id>"]
          }]
        }
      }'
    ```
  </Step>

  <Step title="Verify routing">
    Check that each monitor's incidents route to the correct channel by reviewing the notification dispatches:

    ```bash theme={null}
    curl "https://api.devhelm.io/api/v1/notification-dispatches?incident_id=<incident-id>" \
      -H "Authorization: Bearer $DEVHELM_API_TOKEN"
    ```
  </Step>
</Steps>

## How matching works

Remember: **all matching policies run**. In the setup above:

* A `payments`-tagged monitor failing triggers the "Payments team" policy **and** the catch-all
* An `infrastructure`-tagged monitor failing triggers only the catch-all
* If you don't want the catch-all for tagged monitors, add a `monitor_tag_in` rule to it as well

## Combining rules

Match rules use AND logic within a policy. Combine tags with other criteria:

```json theme={null}
{
  "name": "Critical payments",
  "matchRules": [
    { "type": "monitor_tag_in", "values": ["payments"] },
    { "type": "severity_gte", "value": "DOWN" }
  ],
  "escalation": {
    "steps": [
      { "delayMinutes": 0, "channelIds": ["<payments-slack-id>"] },
      { "delayMinutes": 5, "channelIds": ["<payments-pagerduty-id>"], "requireAck": true }
    ]
  },
  "priority": 20
}
```

This only fires for `DOWN` incidents on `payments`-tagged monitors, while a lower-priority policy handles `DEGRADED` events via Slack only.

## Next steps

<CardGroup cols={2}>
  <Card title="Notification policies" icon="filter" href="/alerting/notification-policies">
    Full match rule reference and priority logic.
  </Card>

  <Card title="Tiered escalation" icon="arrow-up-right-dots" href="/guides/tiered-escalation">
    Add multi-step escalation to your tag-based policies.
  </Card>

  <Card title="Testing your alerts" icon="vial" href="/guides/testing-your-alerts">
    Validate routing end-to-end.
  </Card>
</CardGroup>
