opsbeginner5 min setupby Mantle
Scheduled health check with email alert
Ping an endpoint every 5 minutes; if it does not return 200, email the on-call address with the status code.
Drag to pan, pinch to zoom. This is the real graph the template installs.
How it works
What it does
- Every 5 minutes, GET the health URL (one retry after 2 s).
- Healthy? routes a non-200 status to Alert on-call; a 200 ends quietly.
- The dashed error edge from the request also alerts when the request itself fails (timeout, DNS).
Setup
- Change the
urlon GET /health and theinterval_secon the trigger. - Set the recipient and a SendGrid / SMTP connection on Alert on-call.
Nodes 5
- 01Every 5 minutestrigger.scheduleTrigger
- 02GET /healthhttp.requestHTTP
- 03Healthy?control.branchLogic
- 04Alert on-callmail.sendDestination
- 05Healthy — stopcontrol.filterLogic
View template JSON
{
"format": "mantle-workflow/v1",
"id": "ops-http-health-check",
"name": "Scheduled health check with email alert",
"graph": {
"nodes": [
{
"id": "schedule",
"type": "trigger.schedule",
"label": "Every 5 minutes",
"config": {
"interval_sec": 300,
"timezone": "UTC"
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 60,
"y": 220
}
},
{
"id": "ping",
"type": "http.request",
"label": "GET /health",
"config": {
"method": "GET",
"url": "https://example.com/health",
"timeout_seconds": 10
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 380,
"y": 220
},
"retry": {
"max_attempts": 2,
"backoff": "fixed",
"initial_ms": 2000,
"max_ms": 2000
}
},
{
"id": "branch_healthy",
"type": "control.branch",
"label": "Healthy?",
"config": {
"mode": "first_match"
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 700,
"y": 220
}
},
{
"id": "send_alert",
"type": "mail.send",
"label": "Alert on-call",
"config": {
"to": "oncall@example.com",
"subject": "[ALERT] health check failed ({{ steps.ping.status_code }})",
"body_text": "GET https://example.com/health returned {{ steps.ping.status_code }} at {{ $now }}.\n\nBody:\n{{ steps.ping.body }}"
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 1020,
"y": 410
}
},
{
"id": "all_good",
"type": "control.filter",
"label": "Healthy — stop",
"config": {
"expr": "status_code == 200"
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 1020,
"y": 30
}
}
],
"edges": [
{
"from": "schedule",
"to": "ping"
},
{
"from": "ping",
"to": "branch_healthy"
},
{
"from": "branch_healthy",
"to": "send_alert",
"branch": "true",
"condition": {
"match": "all",
"rules": [
{
"left": "status_code",
"op": "not_equals",
"right": 200
}
]
},
"label": "not 200"
},
{
"from": "branch_healthy",
"to": "all_good",
"branch": "false",
"label": "200 OK",
"priority": 1
},
{
"from": "ping",
"to": "send_alert",
"branch": "error",
"label": "request failed"
}
]
}
}Use it, then make it yours.
Templates install as drafts. Change anything, and Workflow Health re-checks the graph on every save.