Skip to content

Send alerts to email

An email recipient sends outage and recovery alerts to an address you choose, instead of (or alongside) a webhook recipient — the other recipient type the dashboard can create today. (um-api also accepts type: "slack" and type: "pagerduty" recipients directly through the API; see Choose who gets alerts.) Unlike a webhook recipient, an email recipient has a confirmation step: it starts pending and sends nothing until the mailed confirmation link is followed.

  1. Go to Recipients and click Create recipient.
  2. Choose Email, enter the address, pick which events to notify on, and click Create recipient.
  3. You’ll see Confirmation sent to <address> — alerts start once the recipient confirms. Click Done.
  4. Check that address’s inbox and follow the confirmation link.
  5. Attach the recipient to a monitor from that monitor’s Recipients section, the same way you would any other recipient type — see the alert recipients guide.

A recipient’s status shows on its row in the dashboard: active, awaiting confirmation (pending), or unsubscribed (disabled).

An email recipient’s row in the dashboard, showing its status badge and a Resend confirmation button

Terminal window
curl -X POST https://api.uptimemonitoring.com/api/v1/recipients \
-H "Authorization: Bearer $UPTIMEMONITORING_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "on-call",
"type": "email",
"config": {"address": "oncall@example.com"},
"events": ["down", "up", "flapping"]
}'

The response’s status field reads "pending" immediately after creation — a 201 here does not mean the confirmation mail actually arrived (see Troubleshooting). Attach it to a monitor using the full-replacement PUT endpoint described in the alert recipients guide.

Through MCP, create_monitor’s recipients argument can attach an existing email recipient by id at monitor-creation time; creating the email recipient itself, and resending or checking its confirmation, has no MCP tool today — use the REST API or the dashboard for those.

The default email daily cap is 200 sends per account per UTC calendar day (DefaultEmailDailyCap in um-api’s internal/webhook/delivery.go) — the dispatcher can override this default per deployment. A few things this number is not:

  • It’s account-level, not per-recipient. All of an account’s email recipients share the same 200-send counter for the day.
  • It’s a hard stop at the boundary, not a queue. A delivery that arrives after the account has hit the cap for the UTC day is marked failed immediately and is not retried automatically once the next day’s counter resets — a person has to notice and resend, or wait for the next qualifying event.
  • It’s not an exact count of messages you’ll receive. Email delivery is at-least-once, like every other recipient type: if the send succeeds but the worker crashes before recording that outcome, the next poll can resend the same alert without consuming another cap slot. Don’t treat 200 as a guaranteed, exact number of emails sent or received in a day.

See Choose who gets alerts for the recipient name length limit (255 bytes) shared by every recipient type.

A recipient has been pending for a while and isn’t getting alerts. A pending recipient sends no alerts at all — it must be confirmed first. Check its status on the Recipients page, and resend the confirmation if needed (see below). Creating or changing an email recipient’s address sends its confirmation mail after the API call already succeeded, and that send is best-effort: a successful response doesn’t guarantee the mail arrived.

Retrying my PATCH didn’t resend the confirmation. It won’t — submitting the same, unchanged address again doesn’t trigger a second confirmation mail. Use the dedicated resend endpoint instead:

Terminal window
curl -X POST https://api.uptimemonitoring.com/api/v1/recipients/42/confirm/resend \
-H "Authorization: Bearer $UPTIMEMONITORING_API_KEY"

This can return 202 (resent), 409 (two different meanings — see below), 429 (resent too recently — there’s a 60-second cooldown, plus a per-address hourly rate limit; the response includes a Retry-After header), or 503 (the resend attempt itself failed to send). A 202 means a new confirmation mail was sent, not that the recipient is active again: it stays pending, sending nothing, until that new link is followed. Resend only accepts a recipient whose type is email and whose status still permits a fresh confirmation attempt — it has no effect on one that’s already disabled, which this endpoint rejects outright.

A 409 here means one of two different things, and the response body doesn’t always make the distinction obvious:

  • The recipient is already confirmed. Nothing to do — it’s active.

  • A concurrent resend, address change, or deletion invalidated this specific mailed link after it was sent. This happens when the link was emailed successfully, but by the time the send finished, something else had already superseded the pending confirmation hash it carries — a second resend, an address change, or the recipient being deleted mid-flight. The mail arrived, but following that particular link returns an error rather than confirming.

    Before retrying, re-fetch the recipient (GET /api/v1/recipients/{recipientID}) to find out which of these it was — a blind retry only works for one of the two causes:

    • It still exists and is pending. The invalidation was a resend or an address change. Request another resend to get a link that’s current.
    • It’s gone (404). It was deleted mid-flight — there’s no recipient left for a resend to target, so requesting one just gets another 409/404. Create a replacement recipient with the same name, default, and events, then reattach it to every monitor the deleted recipient was on (see Choose who gets alerts for the read-merge-write recipients form), and have the owner follow the new confirmation link.

A recipient is disabled and resend doesn’t fix it. A recipient reaches disabled only through its mailed unsubscribe link, and there is no API or dashboard action that re-enables it from there. The only recovery is to delete it and create a replacement — but deleting it first detaches it from every monitor it was on, so a careless delete-then-create leaves those monitors unalerted until you notice and reattach them by hand. There is no gap-free recovery from a disabled recipient — step 4 below attaches the replacement before it’s confirmed specifically to minimize that window, not eliminate it:

  1. Read and save the disabled recipient’s name, default, and events (GET /api/v1/recipients/{recipientID}), plus, for each attached monitor, this recipient’s down_delay_s from that monitor’s structured recipients array (GET /api/v1/monitors/{monitorID}/recipients).
  2. Create the replacement email recipient with the same name, default, and events. It starts pending, same as any new email recipient.
  3. Attach the replacement to every saved monitor while it’s still pending, using the saved down_delay_s and the read-merge-write recipients form from Choose who gets alerts. Attachment validation checks only recipient ownership, not status, so a pending recipient attaches exactly like an active one. Verify every attachment landed before continuing.
  4. Only now follow the replacement’s confirmation link so it reaches active. Attaching before confirming matters: a pending recipient sends nothing, so any event that occurs while it’s still pending goes undelivered and isn’t retried once it activates — but attaching first stops that gap from growing past confirmation. Confirming first and attaching afterward would leave that same gap open for the entire time it takes to migrate every monitor, instead of just until one confirmation click.
  5. Once active, verify delivery with the recipient’s test-send endpoint (POST /api/v1/recipients/{recipientID}/test) or a controlled down/up transition — not by waiting for the next check cycle.
  6. Immediately before deleting the disabled recipient, re-read every affected monitor’s recipients array directly and confirm the replacement is attached with the original’s down_delay_s, retrying any monitor where it’s missing or has drifted. Separately, re-read the disabled recipient’s own monitor_ids, in case a monitor was attached mid-recovery and missed your step 1 snapshot — migrate that attachment too.
  7. Only then delete the disabled recipient.

This procedure assumes no other writer changes an affected monitor’s recipients for its entire duration, not only at the start — step 6’s re-read is a mitigation against a concurrent change, not a guarantee against one. No step here is atomic with another, so a crash partway through can leave some monitors still on the disabled recipient; re-check their attached recipients afterward.

A monitor has email recipients attached but nobody’s getting alerted. A pending or disabled recipient doesn’t make a monitor alert-capable, even though it’s attached. Confirm the recipient is active before relying on it — attaching a recipient is not the same as it being able to send.