On this page
The four parts of a good alert
| Part | What it says | Example line |
|---|---|---|
| What | The endpoint, the service, and the change in plain words | GET /orders/{id} in orders-api: total removed from the 200 response |
| Who | Who owns the endpoint and who made the change, so the reader knows whom to ask | Owned by payments-team · PR #1284 by dana-k |
| Severity | Breaking or not, and whether it is live or still a pull request | Breaking · not merged yet |
| Action | What the reader should do, and where to answer | Read amount instead, or reply on the PR before it merges |
The order matters. The title is the first thing people see in the channel and in the notification; in Slack the notification shows the message’s text field, so make that the same one-line summary. Put the endpoint and the word “breaking” there, not the service name or a greeting.
Four habits that make alerts ignored
- A count instead of a change. “3 breaking changes in orders-api” makes every reader open a link to learn whether it is theirs.
- `@here` or `@channel`. It pings everyone who is online to tell the one team that cares. People mute the channel, and then they miss the next alert too.
- A wall of diff. Twenty lines of YAML hide the one line that matters. Link to the diff; say the change in a sentence.
- A new message for every update. A pull request that is pushed five times should not post five alerts. Edit the first message and reply in its thread when something important happens.
Example: a hand-built alert
If you send alerts yourself, from a CI job or a script, this is a shape that holds the four parts. The text sits in the fields each platform uses for notification previews.
Slack: an incoming webhook
Create a Slack app
At api.slack.com/apps, choose Create New App, pick a name and the workspace.
Turn on incoming webhooks
Open Incoming Webhooks, switch on Activate Incoming Webhooks, then Add New Webhook to Workspace and pick the consuming team’s channel.
Store the URL as a secret
The URL contains a secret. Keep it in your CI secret store, never in the repository: Slack looks for leaked webhook URLs and revokes them.
{
"text": "Breaking change: GET /orders/{id} (orders-api)",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Breaking change: `GET /orders/{id}`* in orders-api"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Removed the required property `total` from the 200 response.\nOwned by payments-team · PR #1284 by dana-k · not merged yet\n*What to do:* read `amount` instead, or reply on the PR before it merges."
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Open pull request"
},
"url": "https://github.com/example/orders-api/pull/1284"
}
]
}
]
}curl -X POST -H "Content-Type: application/json" \
--data @alert.json "$SLACK_WEBHOOK_URL"- `text` is not optional. With
blocks, Slack usestextas the notification and screen-reader fallback. Make it the one-line summary. - One webhook, one channel. An incoming webhook posts to the channel picked when it was created; you cannot override the channel, name or icon. Routing to several teams means one URL per team’s channel.
- No edits. An incoming webhook cannot delete a message, and returns no message
tsto edit it with. To edit one message as the pull request moves on, and reply in its thread, you need a Slack app with a bot token:chat.postMessage, thenchat.updatewith the message’sts, andthread_tsfor replies. - Limits. A section’s text is at most 3,000 characters.
chat.postMessageallows about one message per second per channel, with short bursts.
Microsoft Teams: a Workflows webhook
Old Teams webhook URLs no longer work
Microsoft retired Office 365 connectors in Teams, including the Incoming Webhook connector, between May 18 and May 22, 2026. A guide that tells you to add the “Incoming Webhook” connector to a channel is out of date. The replacement is a webhook in the Workflows app, built on Power Automate.
Open Workflows on the channel
In Teams, open More options (…) next to the consuming team’s channel and choose Workflows.
Pick the template
Choose Send webhook alerts to a channel, confirm the team and channel, and select Save.
Copy the webhook URL
Copy the link the workflow shows and store it as a secret, like the Slack URL.
Add a co-owner
A workflow belongs to the person who created it, not to the channel. Add a co-owner so alerts do not stop when that person leaves.
{
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"text": "Breaking change: GET /orders/{id}",
"weight": "Bolder",
"size": "Medium",
"wrap": true
},
{
"type": "TextBlock",
"text": "Removed the required property total from the 200 response.",
"wrap": true
},
{
"type": "FactSet",
"facts": [
{
"title": "Service",
"value": "orders-api"
},
{
"title": "Owner",
"value": "payments-team"
},
{
"title": "Status",
"value": "PR #1284, not merged yet"
},
{
"title": "What to do",
"value": "Read amount instead, or reply on the PR"
}
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "View pull request",
"url": "https://github.com/example/orders-api/pull/1284"
}
]
}
}
]
}- Adaptive Cards. Workflows webhooks take Adaptive Card and MessageCard payloads; MessageCard buttons that post back do not work, so use an Adaptive Card. A link button (
Action.OpenUrl) is fine. - Who posts it. The message shows the Workflows bot, not your name or icon.
- Limits. A message can be at most 28 KB, and more than four requests a second are throttled. Retry with backoff.
- Private channels can be picked in the Workflows app since April 2026.
Email: the fallback that always works
Some teams live in email, and chat channels break: a bot is removed, a channel is archived. Put the severity and the endpoint in the subject, because that is all most people read: “[BREAKING] GET /orders/{id} (orders-api)”. Then the same four parts in the body.
What Graphwake sends
Graphwake builds these messages for you from your OpenAPI spec and sends each one to the teams subscribed to the endpoint, in the channel each team picked: Slack, Microsoft Teams or email. The one exception, a one-time note to a team Discovery suggests, is below. Every team has at most one chat channel. The examples below follow the message format Graphwake uses; names and links are made up.
Breaking change in PR #1284
Service: orders-api
Endpoint: GET /orders/{id}
Owned by payments-team
Change: Removed the required property `total` from the response with the `200` status
Author: dana-k
PR: https://github.com/example/orders-api/pull/1284
[ Open pull request ]In Slack a breaking change gets a siren emoji before the title; in Teams the same lines arrive as an Adaptive Card with a highlighted title and a View pull request button. There is one message per endpoint for each subscribed team, so a team reads only about the endpoints it calls.
Subject: [BREAKING] New change notification: GET /orders/{id} (orders-api)
Endpoint: GET /orders/{id}
Service: orders-api
Owned by payments-team
Change: Removed the required property `total` from the response with the `200` status
Breaking: yes, breaking change
Status: new notification
This change is not live yet (open pull request).
Author: dana-k
PR: https://github.com/example/orders-api/pull/1284How the message changes as the pull request moves
| What happens | In Slack or Teams | By email |
|---|---|---|
| The PR is pushed again | The same message is edited to show the current state | No new mail |
| A non-breaking change becomes breaking (teams on “All changes”) | Edited, plus a thread reply: “This change is now breaking.” | A new mail |
| The PR merges | Title becomes “Published: …”, plus a reply: “Published to live.” | “Change published” mail |
| The PR closes without merging | Title becomes “PR #1284 closed”, plus a reply: “PR closed without merging.” | “Change cancelled” mail |
A team on the default, breaking changes only, never saw the non-breaking version, so its first message arrives when the change turns breaking. If someone deletes the message, the next update starts a new one. Graphwake never adds @here, @channel or user mentions: text from a spec or a pull request is escaped, so it cannot become a mention or a link.
Discovery can add one more message: a team suggested at 60% or more for the endpoint, but not subscribed, gets a one-time “This may affect you” note when a breaking change goes live. Admins can turn it off.
Only subscribed teams
Each consumer team subscribes to the endpoints it calls. Teams that are neither subscribed nor suggested by Discovery hear nothing.
One message per change
Edited in place as the pull request moves, with a thread reply only when it merges, closes or turns breaking.
Email when chat breaks
If a team’s channel is gone or the bot was removed, that alert goes by email, and admins are told the channel needs fixing.
Breaking first
Teams get breaking changes by default. A team can turn on all changes for itself.
The severity in a Graphwake message is “Breaking change” or “Change”. The impact score of the whole change set, and every team it reaches, are on the change in the dashboard, where each team can mark the change handled.
Set it up
Connect Slack or Microsoft Teams
An admin connects the Slack workspace, or links the Microsoft tenant and adds the Graphwake app to the teams that should get alerts.
Pick each team’s channel
On the team’s Notifications tab, pick its channel. A team without a channel gets alerts by email.
Send a test alert
Send test alert on the same tab sends a test message through the same route a real alert takes.
Subscribe to endpoints
Each consumer team marks the endpoints it calls. The next breaking change on one of them reaches that team in its own channel.
When a webhook script alone is enough
- One API, a few known consumers. A CI job that posts the alert above to their channels does the job.
- Every consumer reviews your pull requests. The diff comment there is the alert. See oasdiff in a GitHub Action.
- Public API consumers. Customers outside your company are not in your Slack; a changelog and an email list reach them.
A script stops scaling when the list of who calls what is the hard part. That list, kept current by the consumer teams, is what routing alerts to the right teams is about, and how to notify consumers of API changes has a notice template for the cases you write by hand.
Questions
Can I still use an Incoming Webhook in Microsoft Teams?
Not the connector. Office 365 connectors in Teams, including Incoming Webhook, were retired in May 2026. Create a webhook with the Workflows app (“Send webhook alerts to a channel”) and send an Adaptive Card to its URL.
Should an API change alert use @here or @channel?
No. Send it to the channel of the team that calls the endpoint instead. A mention pings everyone who is online to reach the few people who care, and channels that ping too often get muted.
Can a Slack incoming webhook edit a message it posted?
No. An incoming webhook cannot delete a message, and returns no message ts to edit it with. To update one message as a pull request changes, use a Slack app with a bot token and chat.update.
Does Graphwake post to a shared announcement channel?
Only if a team picks that channel. Each team chooses one chat channel, and an alert goes only to the teams subscribed to the changed endpoint, plus a one-time note to teams Discovery suggests strongly.
What happens if the Slack or Teams channel is deleted?
Graphwake sends that alert by email instead, to the team’s email channel or its members, and tells the workspace admins that the channel needs fixing.
Pick an endpoint. See who it reaches. 7-day free trial. Cancel before day 7 and you pay nothing.
Start free trialSources and last verified
- docs.slack.dev/messaging/sending-messages-using-incoming-webhooks/
- docs.slack.dev/reference/methods/chat.postMessage/
- docs.slack.dev/reference/methods/chat.update/
- docs.slack.dev/reference/block-kit/blocks/section-block/
- devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/
- learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook
- support.microsoft.com/en-us/office/create-incoming-webhooks-with-workflows-for-microsoft-teams-8ae491c7-0394-4861-ba59-055e33f75498
Sources checked on 2026-11-09.