Teams Uptime Alerts
Checks every client site each 15 minutes and posts to the client's Teams channel the moment one goes down.
maphttpswitchintegration
Source
/**
* Uptime alerts in Microsoft Teams. Checks each client site every 15
* minutes and posts to the client's Teams channel the moment one goes
* down. SMB teams live in Teams, so the alert lands where they already
* work.
*
* Setup:
* 1. swirls add microsoft send_channel_message
* 2. Deploy, then authorize the Microsoft connection in Cloud -> Connections.
* 3. Fill in each site's team and channel ids below. Find them with the
* list_chats and get_chat actions, or from Teams channel links.
*/
connection client_microsoft {
label: "Client Microsoft 365"
provider: microsoft
}
schedule every_15_minutes {
label: "Every 15 Minutes"
cron: "*/15 * * * *"
}
workflow check_client_sites {
label: "Check Client Sites"
description: "Ping every client site and post a Teams alert for any that are down."
root {
type: code
label: "List sites"
code: @ts {
return {
sites: [
{
name: "Acme storefront",
url: "https://www.acme-client.com",
teamId: "REPLACE_WITH_TEAM_ID",
channelId: "REPLACE_WITH_CHANNEL_ID"
},
{
name: "Acme booking portal",
url: "https://book.acme-client.com",
teamId: "REPLACE_WITH_TEAM_ID",
channelId: "REPLACE_WITH_CHANNEL_ID"
}
]
}
}
outputSchema: @json {
{
"type": "object",
"properties": {
"sites": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"url": { "type": "string" },
"teamId": { "type": "string" },
"channelId": { "type": "string" }
}
}
}
}
}
}
}
node check_each {
type: map
label: "Check each site"
items: @ts { return context.nodes.root.output.sites }
maxItems: 20
subgraph {
root {
type: code
label: "Site under test"
inputSchema: @json {
{
"type": "object",
"properties": {
"name": { "type": "string" },
"url": { "type": "string" },
"teamId": { "type": "string" },
"channelId": { "type": "string" }
}
}
}
code: @ts { return context.iteration.item }
outputSchema: @json {
{
"type": "object",
"properties": {
"name": { "type": "string" },
"url": { "type": "string" },
"teamId": { "type": "string" },
"channelId": { "type": "string" }
}
}
}
}
node ping {
type: http
label: "Ping site"
url: @ts { return context.nodes.root.output.url }
failurePolicy: {
strategy: "fallback"
fallbackValue: {}
}
}
node evaluate {
type: code
label: "Evaluate response"
code: @ts {
const statusCode = context.nodes.ping.meta ? context.nodes.ping.meta.status : 0
const isUp = statusCode >= 200 && statusCode < 400
return { status: isUp ? "up" : "down", statusCode: statusCode }
}
}
node route {
type: switch
label: "Route by status"
cases: ["up", "down"]
router: @ts { return context.nodes.evaluate.output.status }
}
node post_alert {
type: integration
label: "Post Teams alert"
connection: client_microsoft
action: microsoft_send_channel_message
params: @ts {
const site = context.nodes.root.output
const code = context.nodes.evaluate.output.statusCode
return {
team_id: site.teamId,
channel_id: site.channelId,
importance: "urgent",
body: {
contentType: "text",
content: "DOWN: " + site.name + " (" + site.url + ") returned status " + code + ". We are on it."
}
}
}
}
node log_ok {
type: code
label: "Log healthy"
code: @ts {
return { name: context.nodes.root.output.name, status: "up" }
}
}
flow {
root -> ping
ping -> evaluate
evaluate -> route
route -["down"]-> post_alert
route -["up"]-> log_ok
}
}
}
flow {
root -> check_each
}
}
trigger on_interval {
schedule:every_15_minutes -> check_client_sites
enabled: true
}
Flow
Trigger to workflow
every_15_minutesschedule
check_client_sites
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Workflow nodes
CODE
Code Node
List sites
MAP
Map Node
Check each site
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.