API Documentation
The MyUpMonitor API lets you programmatically manage monitors, incidents, status pages, and notifications. Available on Business and Enterprise plans.
Base URL
https://myupmonitor.com/apiRate Limits
| Plan | Limit |
|---|---|
| Free | 30 req/min |
| Pro | 100 req/min |
| Business | 1,000 req/min |
| Enterprise | 1,000 req/min |
Rate limit headers: X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After
Authentication
Create an API key in Dashboard → Settings → API Keys. Include it as a Bearer token:
Authorization: Bearer mum_your_api_key_here
curl -H "Authorization: Bearer mum_your_key" \ https://myupmonitor.com/api/monitors
API Key Scopes
API keys can be scoped to limit access. Keys with no scopes have full access (backwards compatible). Create scoped keys via POST /api/keys with a scopes array.
Available Scopes
| Scope | Grants Access To |
|---|---|
monitors:read | List and view monitors |
monitors:write | Create, update, delete monitors |
incidents:read | List and view incidents |
incidents:write | Create, update, delete incidents |
notifications:read | List notification channels |
notifications:write | Create, update, delete channels |
account:read | View account info |
status-pages:read | List and view status pages |
status-pages:write | Create, update status pages |
reports:read | View SLA and weekly reports |
{
"name": "CI/CD Read-Only",
"scopes": ["monitors:read", "incidents:read"]
}
// Response (raw key shown once):
{
"key": { "id": "uuid", "name": "CI/CD Read-Only", "scopes": ["monitors:read", "incidents:read"] },
"rawKey": "mum_..."
}Keys with empty scopes: [] or no scopes field have full access. A scoped key trying to access an endpoint outside its scopes receives 403 Forbidden.
Monitors
// Response
[
{
"id": "uuid",
"website": "https://example.com",
"check_type": "http",
"interval_seconds": 60,
"active": true,
"last_status": 200,
"uptime_24h": 99.95,
"avg_response_ms": 245
}
]curl -X POST /api/monitors \
-H "Authorization: Bearer mum_key" \
-H "Content-Type: application/json" \
-d '{"website":"https://example.com","check_type":"http","interval_seconds":60}'// Response
{
"uptime_percent": 99.95,
"avg_response_ms": 245,
"total_checks": 1440,
"incidents": 1,
"history": [
{ "timestamp": "2026-03-25T10:00:00Z", "status": 200, "response_ms": 230, "region": "us-east" }
]
}Periods: 24h, 7d, 30d
Monitor Check Types
When creating a monitor, set check_type to one of the following. Each type accepts different parameters.
| Type | Description | Extra Fields |
|---|---|---|
http | HTTP(S) status check | http_keyword, http_keyword_negate, response_time_threshold_ms |
ssl | SSL certificate expiry | Alerts at 30/14/7/1 days before expiry |
tcp | TCP port connectivity | tcp_port (required, 1-65535) |
dns | DNS record monitoring | dns_record_type (A/AAAA/MX/TXT/CNAME), dns_expected_value |
heartbeat | Dead man's switch | Returns heartbeat_token — ping /api/heartbeat/:token to report health |
api | Multi-step API checks | api_check_steps (JSON array of steps) |
{
"url": "example.com",
"check_type": "dns",
"dns_record_type": "A",
"dns_expected_value": "93.184.216.34",
"interval_seconds": 600
}{
"url": "https://example.com",
"check_type": "http",
"http_keyword": "Welcome",
"http_keyword_negate": false,
"response_time_threshold_ms": 2000,
"interval_seconds": 300
}// api_check_steps is a JSON string containing an array of steps:
// Each step: name, method, url, headers, body, assertions, extract
//
// Step fields:
// assertions: [{type: "status", value: "200"},
// {type: "body_contains", value: "ok"},
// {type: "json_path", path: "data.id", value: "123"}]
// extract: {"token": "data.access_token"} (dot-notation JSON path)
//
// Variables from extract are available in later steps as {{token}}Steps run sequentially with fail-fast. SSRF protection on all step URLs.
Escalation Policies
Define multi-step alert escalation chains. If nobody acknowledges an alert, it escalates to the next tier of channels.
{
"name": "Production Alerts",
"steps": [
{ "delayMinutes": 0, "channelIds": ["slack-channel-id"] },
{ "delayMinutes": 5, "channelIds": ["pagerduty-channel-id"] },
{ "delayMinutes": 15, "channelIds": ["email-channel-id"] }
]
}Step 1 fires immediately. Subsequent steps fire if no acknowledgment within the delay.
Stops further escalation for this alert. Recovery auto-acknowledges.
Incidents
Query params: monitor_id, active=true
{
"monitor_id": "uuid",
"title": "API degradation",
"status": "investigating"
}{
"status": "identified", // investigating | identified | monitoring | resolved
"message": "Root cause identified — deploying fix"
}Status Pages
{
"name": "Acme Status",
"slug": "acme",
"custom_domain": "status.acme.com" // optional, Business+ plans
}Notification Channels
// Slack
{ "name": "Ops Slack", "type": "slack", "config": { "webhook_url": "https://hooks.slack.com/..." } }
// Discord
{ "name": "Alerts", "type": "discord", "config": { "webhook_url": "https://discord.com/api/webhooks/..." } }
// Webhook
{ "name": "Custom", "type": "webhook", "config": { "url": "https://example.com/hook", "secret": "hmac_secret" } }Heartbeat Pings
Heartbeat monitors work like a dead man's switch. Create a heartbeat monitor to get a unique ping URL. Your cron job or service should hit this URL on a schedule. If we don't receive a ping within the expected interval + grace period, we alert.
# Add to your crontab: */5 * * * * curl -fsS -o /dev/null https://myupmonitor.com/api/heartbeat/your_token_here # Or from a script: curl -X POST https://myupmonitor.com/api/heartbeat/your_token_here
Also accepts GET for simplicity. Returns { "ok": true } on success.
{
"url": "Nightly Backup Job",
"check_type": "heartbeat",
"interval_seconds": 86400,
"heartbeat_grace_minutes": 30
}
// Response includes heartbeat_token:
{
"monitor": {
"id": "uuid",
"heartbeat_token": "a1b2c3..." // Use this in your ping URL
}
}Webhook Verification
When using webhook notification channels with a secret, we sign the payload with HMAC-SHA256. Verify like this:
const crypto = require('crypto');
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return `sha256=${expected}` === signature;
}
// In your handler:
const sig = req.headers['x-signature-256'];
if (!verifyWebhook(rawBody, sig, 'your_secret')) {
return res.status(401).send('Invalid signature');
}Webhook Payload
{
"event": "monitor.down",
"monitor": {
"id": "uuid",
"website": "https://example.com",
"check_type": "http"
},
"status": {
"http_status": 503,
"response_ms": 5000,
"error": "timeout",
"region": "us-east"
},
"timestamp": "2026-03-25T10:00:00Z"
}Events: monitor.down, monitor.up, ssl.expiring