Send Simrix Monitor alerts to Microsoft Teams
Simrix Monitor does not post to Microsoft Teams directly. A webhook pointed at a relay gets alerts into a channel: the relay verifies the signature and builds the card format Teams expects. This page covers the setup and its limits.
There is no native integration for this yet. Alerts get there through a webhook pointed at a relay you control. The steps below set that up.
Steps
- In Teams, add an incoming webhook connector to the channel and copy its URL.
- Create a relay that can receive a webhook and call that URL.
- In Simrix Monitor, open Account → Webhooks, choose Add webhook, and paste the relay's URL.
- Pick the events and save, copying the signing secret before you leave the page.
- In the relay, verify the signature, then POST a card to the Teams connector with the monitor name, what failed and a link to the check.
Why does this need a relay?
A Teams connector expects a card format. Simrix Monitor sends its own JSON envelope with event, timestamp, workspaceId, monitor and run, which a connector will not render.
Since each delivery is attempted once with no retry, a rejected request is a lost alert rather than a delayed one. The relay's job is to turn one shape into the other.
What does Simrix Monitor send?
A single JSON POST per event. Here is a real body for a failed check.
{
"event": "monitor_failed",
"timestamp": "2026-09-14T14:03:11.482Z",
"workspaceId": "clz9a1b2c3d4e5f6g7h8i9j0",
"monitor": {
"id": "clz8m0n1o2p3q4r5s6t7u8v9",
"name": "Checkout smoke test",
"type": "page_check",
"url": "https://shop.example.com/checkout"
},
"run": {
"id": "clz7r0u1n2i3d4e5f6g7h8i9",
"status": "failed",
"changeDetected": false,
"aiSummary": "We could not find “#place-order” on the page at step 3 of 6. It may have been renamed or moved, or the page may not have got that far.",
"failureSummary": "We could not find “#place-order” on the page at step 3 of 6. It may have been renamed or moved, or the page may not have got that far.",
"failureReasonCode": "element_not_found",
"durationMs": 31204,
"httpStatus": 200,
"screenshotUrl": "/api/artifacts/clz7r0u1n2i3d4e5f6g7h8i9/screenshot.png",
"diffScreenshotUrl": null,
"shareUrl": "https://simrixmonitor.com/r/Zq8nT2xK9pLm4vR7wYbC1dF3hJ5kN6sQ8tU0xW2yA4E"
}
}
Which events can fire?
| Event | When it fires |
|---|---|
monitor_failed |
A scheduled check on a workflow monitor failed. |
monitor_recovered |
A workflow monitor passed again after a failure. |
change_detected |
A change monitor found a meaningful difference from its baseline. |
What is in the body?
| Field | Type | Notes |
|---|---|---|
event |
string | One of the three event names. |
timestamp |
string | ISO 8601, set when the request is sent, not when the check ran. |
workspaceId |
string | Your workspace. |
monitor.id |
string | Use this to correlate with your own records. |
monitor.name |
string | The monitor's name as you set it. |
monitor.type |
string | The monitor's kind, for example page_check or change_monitor. |
monitor.url |
string | The URL the check started from. Empty string if none was set. |
run.id |
string | The check's id. |
run.status |
string | For example passed or failed. |
run.changeDetected |
boolean | True only on change_detected. |
run.aiSummary |
string or null | The plain-English summary, when one was produced. |
run.failureSummary |
string or null | Why the check failed. Null on success events. |
run.durationMs |
number or null | How long the check took. |
run.httpStatus |
number or null | The response code of the final page. |
run.screenshotUrl |
string or null | A path, not a full URL. Prefix it with your Simrix Monitor address, and note it needs a signed-in session to open. |
run.diffScreenshotUrl |
string or null | The highlighted difference image. Only on change_detected. |
run.shareUrl |
string or null | A public link to this check's evidence, when the monitor has shareable reports switched on. Opens with no sign-in, so this is the link to forward. Null when sharing is off for that monitor. |
Which headers arrive?
| Header | Value | Notes |
|---|---|---|
Content-Type |
application/json |
The body is always JSON. |
X-Simrix-Signature |
sha256=<hex digest> |
HMAC-SHA256 of the raw request body, keyed with your signing secret. |
X-Simrix-Event |
monitor_failed |
The same value as the body's event field, so you can route before parsing. |
User-Agent |
Simrix-Monitor-Webhook/1.0 |
Fixed. Useful for filtering your own logs. |
How do you verify the signature?
The signature is an HMAC-SHA256 of the raw request body, keyed with your signing secret and written as lowercase hex behind a sha256= prefix.
import crypto from "node:crypto";
// Sign the RAW body. Re-serialising parsed JSON will not match.
function isFromSimrixMonitor(rawBody, header, secret) {
const expected =
"sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(header ?? "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
What should your receiver expect?
- Delivery is attempted once. A non-2xx response, a connection error or a timeout is logged and dropped. There is no retry, no backoff and no dead-letter queue, so treat a missed delivery as possible and reconcile from the app when it matters.
- The timeout is 10 seconds for the whole request. Acknowledge quickly and do your own work afterwards, rather than processing before you respond.
- The signature covers the raw body only. No timestamp is included, so there is no replay protection built in. If that matters, record
run.idand ignore ids you have already handled. - Change monitors only fire
change_detected. A change monitor that errors does not sendmonitor_failed, and change monitors never sendmonitor_recovered. Subscribing tomonitor_failedwill not tell you a change monitor is broken. - Failure and recovery webhooks follow the email toggles. Turning off Failure alerts or Recovery alerts on the notifications page turns off the matching webhook as well.
- Only scheduled checks send anything. Running a check by hand to try something out fires no webhook and sends no email.
14 days, no card required.
Frequently asked questions
Is a Microsoft Teams app planned?
There is no Teams integration today, and none is announced. A webhook plus a relay is the supported route.
Can the card include the screenshot?
Not directly. The screenshot path in the request body is relative and requires a signed-in session, so link to the check instead of embedding the image.
Last updated