← All guides

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:

 create an API key
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:

 auth header
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:

 create a check
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):

 list checks
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:

 pause a check
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:

 create a channel
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:

 attach a channel
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.