Guide · API
Automate Mortemain with the REST API
Everything the dashboard does, create a check, pause it, wire up a channel, is one HTTP call. A Bearer key, five endpoints, no SDK required.
1. Get an API key
The API is available on paid plans; a free account can hold keys but they stay inactive until you upgrade. Create and revoke keys in the dashboard under Settings → API keys (space owners only): give the key an optional note and its full value is shown once, right after you create it. You can also mint additional keys (one per integration, easy to tell apart later) by calling the API itself with a key you already hold:
curl -s -X POST https://app.mortemain.com/api/keys \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"ci-pipeline"}' # -> 201 {"public_id":"...", "key":"mm_live_...", "note":"store this key now; it is not shown again"}
The full key is only ever shown in that response. Store it in a secrets manager, not in a script or a commit.
2. Authenticate
Every /api/ request needs the key as a Bearer token in the Authorization header. A missing or invalid key gets a plain 401, nothing else:
Authorization: Bearer mm_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # missing / wrong key -> 401 {"error":"unauthorized"}
3. Create a check
name is the only required field. Give it a period_seconds schedule or a cron_expr one (default is period); tz, grace_seconds and tags are optional and default to UTC, 0 and none:
curl -s -X POST https://app.mortemain.com/api/checks \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Nightly export","schedule_kind":"period","period_seconds":86400,"grace_seconds":900,"tags":["export"]}' # -> 201 {"public_id":"...", "ping_url":"https://ping.mortemain.com/..."}
Use ping_url exactly like a check created by hand: curl it on success, curl /fail on error, per the cron jobs guide. Over your plan's check cap, creation returns 402 (check_limit_reached) instead; too tight a period_seconds or cron_expr returns 400 (interval_too_frequent).
4. List and pause checks
GET /api/checks returns every check in the project (name, state, schedule, tags, timestamps):
curl -s https://app.mortemain.com/api/checks \ -H "Authorization: Bearer $API_KEY" # -> 200 {"checks":[{"public_id":"...","name":"Nightly export","state":"new","paused":false, ...}]}
Pause or resume one by public_id. Omitting the body pauses it (the field defaults to true); send {"paused":false} explicitly to resume:
curl -s -X POST https://app.mortemain.com/api/checks/<public_id>/pause \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"paused":true}' # -> 200 {"ok":true, "paused":true} (or 404 if that public_id doesn't exist)
DELETE on that same /api/checks/<public_id> path removes it for good.
5. Create a channel and attach it
A channel needs a kind, a name and a config shaped for that kind; a webhook (also Slack, Discord and Teams incoming-webhook URLs) just needs url:
curl -s -X POST https://app.mortemain.com/api/channels \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"kind":"webhook","name":"On-call webhook","config":{"url":"https://example.com/hooks/mortemain"}}' # -> 201 {"public_id":"..."}
Then attach it to a check by the channel's public_id:
curl -s -X POST https://app.mortemain.com/api/checks/<public_id>/channels \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"channel":""}' # -> 200 {"ok":true} (or 404 if the check or channel isn't found)
What's next
That covers checks, channels and keys, everything a provisioning script needs. For the check-in side (what to curl from the job itself), see the cron jobs guide; if a ping URL alone isn't enough of a secret for your setup, signed pings add an HMAC signature and a timestamp so a leaked URL can't fake a green.