Whyfire

Blog · 13 October 2026 · 7 minute read

Prometheus alerts to Microsoft Teams after the connector shutdown

Tested with Alertmanager 0.28.1 and Prometheus 3.5.

Quick answer

Teams' old incoming webhooks (Office 365 connectors) stopped working on 22 May 2026. Create a Workflows webhook in the channel instead, and send to it with Alertmanager's msteamsv2_configs receiver, which needs Alertmanager 0.28 or later.

If your alert channel went quiet in May, this is probably why. The replacement takes about ten minutes, and Alertmanager now speaks the new format itself, so you don't need a bridge in between.

What changed

To see where you stand, look for any of the old addresses in your Alertmanager configuration:

grep -rnE 'webhook\.office\.com|outlook\.office\.com|logic\.azure\.com' /etc/alertmanager/

Any match is an address that no longer delivers.

1. Create the webhook in Teams

  1. In the channel, open the ⋯ menu and choose Workflows.
  2. Pick Send webhook alerts to a channel. In Power Automate the same template is called "Post to a channel when a webhook request is received".
  3. Name it after what posts there (for example "Prometheus alerts"), check the team and channel, and finish. Copy the URL it shows.

Treat that URL like a password: the signature in it is the only thing stopping anyone else posting to your channel. Private channels work too, since April 2026.

2. Test it before you touch Alertmanager

Post a minimal card with curl. If this fails, the problem is the workflow, not Alertmanager:

TEAMS_URL='paste the workflow URL here'
curl -sS -o /dev/null -w '%{http_code}\n' -H 'Content-Type: application/json' \
  -d '{"type":"message","attachments":[{"contentType":"application/vnd.microsoft.card.adaptive","content":{"type":"AdaptiveCard","version":"1.4","body":[{"type":"TextBlock","text":"Test from curl","wrap":true}]}}]}' \
  "$TEAMS_URL"

202 means the workflow accepted it, and the card should appear within a few seconds. If you get 202 and no card, the workflow ran and its posting step failed: open the workflow's run history and read the failed step.

3. Point Alertmanager at it

Check your version first with alertmanager --version. The msteamsv2 receiver arrived in 0.28.0, and Linux distribution packages are often older; the official release or container image is current.

Save the URL in its own file, readable only by the user Alertmanager runs as. Then the configuration itself can live in git without the secret:

route:
  receiver: teams
  group_by: ['alertname', 'site']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h

receivers:
  - name: teams
    msteamsv2_configs:
      - webhook_url_file: /etc/alertmanager/teams-url
        send_resolved: true

Check the file, reload, and send a test alert through the real path:

amtool check-config /etc/alertmanager/alertmanager.yml
curl -X POST http://localhost:9093/-/reload
amtool alert add TeamsTest severity=warning --annotation='summary="Test alert, please ignore"' --alertmanager.url=http://localhost:9093

The card arrives after group_wait (30 seconds here), and a "resolved" card follows about five minutes later, when the test alert times out.

4. Make the card readable

The default card is generic. A short title with the alert name and count, and one line per alert, reads better on a phone:

route:
  receiver: teams

receivers:
  - name: teams
    msteamsv2_configs:
      - webhook_url_file: /etc/alertmanager/teams-url
        title: '{{ if eq .Status "firing" }}Firing{{ else }}Resolved{{ end }}: {{ .CommonLabels.alertname }} ({{ len .Alerts }})'
        text: '{{ range .Alerts }}{{ with .Labels.instance }}**{{ . }}**: {{ end }}{{ .Annotations.summary }}{{ "\n\n" }}{{ end }}'

Keep it short. When fifty servers fire at once, a card that lists every label of every alert gets long enough to be useless, and can get too big for Teams to post at all. Grouping alerts well matters more here than templates: see One outage, twenty alerts.

When it doesn't work

What you seeWhyFix
Alertmanager won't load a config with msteamsv2_configsAlertmanager is older than 0.28Upgrade
Nothing arrives, and Alertmanager logs errors for msteamsv2An old or mistyped addressCreate the workflow again and copy the new URL
curl gets 202 but no card appearsThe workflow ran and its posting step failedRead the failed run in the workflow's run history
Cards end with a colleague's name: "… used a Workflow template to send this card"Workflows made from the template show who created themIn Power Automate, save a copy of the workflow, switch Alertmanager to the copy's URL, and delete the original
Alerts stop after someone leavesThe workflow belongs to their accountAdd a co-owner, or create workflows from a shared service account

Alert when Teams delivery breaks

If Teams is the only place alerts go, the alert that says "Teams delivery is broken" goes to Teams. Alertmanager counts its own failed deliveries, so watch that counter and send that one alert somewhere else. This needs Prometheus to scrape Alertmanager's own /metrics:

- alert: AlertmanagerNotificationsFailing
  expr: sum by (integration) (rate(alertmanager_notifications_failed_total[10m])) > 0
  for: 15m
  labels:
    severity: critical
  annotations:
    summary: "Alertmanager can't deliver {{ $labels.integration }} notifications"

Then give it its own route to email (or SMS), so it never depends on the thing that broke:

global:
  smtp_smarthost: 'smtp.example.com:587'
  smtp_from: 'alertmanager@example.com'

route:
  receiver: teams
  group_by: ['alertname', 'site']
  routes:
    - matchers: ['alertname="AlertmanagerNotificationsFailing"']
      receiver: email-fallback

receivers:
  - name: teams
    msteamsv2_configs:
      - webhook_url_file: /etc/alertmanager/teams-url
  - name: email-fallback
    email_configs:
      - to: 'oncall@example.com'

For the case where Alertmanager itself is down, nothing inside it can tell you. That needs a heartbeat from outside: see the watchdog in Alert rules that won't burn you out.

One card per incident instead

Alertmanager groups alerts by their labels, so a database failure that takes down three app servers still arrives as several cards about the app servers. Whyfire posts to Teams through the same kind of workflow, but one card per incident: alarms that share a cause arrive together, with the server where it started at the top. The live demo shows one.