When an alert fires, you want it somewhere visible, not buried in an email thread or a muted Slack channel. Messageboard gives you a persistent widget that shows the current state of any monitored service.
The pattern
Every monitoring alert maps to a Messageboard message with a stable name. When the alert fires, you POST a new version of that message with the alert details. When it resolves, you POST another version saying it is resolved.
alert fires -> POST /api/messages { id: "service-health", content: "DB latency 2800ms" }
alert resolves -> POST /api/messages { id: "service-health", content: "DB latency normal (42ms)" }
The widget always shows the latest state. Your team sees the current answer at a glance.
Example 1: Node.js health-check script
const API_KEY = process.env.MESSAGEBOARD_API_KEY;
const MESSAGEBOARD_URL = "https://msgboard.tech/api/messages";
async function checkService(name, url, thresholdMs = 500) {
const start = Date.now();
try {
const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
const latency = Date.now() - start;
const status =
res.ok && latency < thresholdMs
? `${name} healthy — ${latency}ms`
: `${name} degraded — ${latency}ms (HTTP ${res.status})`;
await postStatus(name.toLowerCase().replace(/\s+/g, "-"), status);
} catch (err) {
await postStatus(
name.toLowerCase().replace(/\s+/g, "-"),
`${name} unreachable — ${err.message}`,
);
}
}
async function postStatus(messageId, content) {
await fetch(MESSAGEBOARD_URL, {
method: "POST",
headers: {
"x-api-key": API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ id: messageId, content, contentType: "TEXT" }),
});
}
Example 2: Generic webhook receiver
import express from "express";
const app = express();
app.use(express.json());
const API_KEY = process.env.MESSAGEBOARD_API_KEY;
const MESSAGEBOARD_URL = "https://msgboard.tech/api/messages";
app.post("/webhook/alert", async (req, res) => {
const { alert_name, status, details } = req.body;
const content = `${alert_name} — ${status}: ${details}`;
const messageId = alert_name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
await fetch(MESSAGEBOARD_URL, {
method: "POST",
headers: {
"x-api-key": API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ id: messageId, content, contentType: "TEXT" }),
});
res.sendStatus(200);
});
Example 3: Direct curl
curl -s -X POST https://msgboard.tech/api/messages \
-H "x-api-key: $MESSAGEBOARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"id":"db-health","content":"Database connections normal","contentType":"TEXT"}'
Dashboard design tips
- Use one message name per service or check.
- Keep the message body short and human-readable.
- Include timestamps when freshness matters.
- Group critical services together in dashboard edit mode.
Continue with the quickstart or browse the full API reference.