---
title: "Send alerts to email"
description: "Create an email recipient, confirm it, attach it to monitors, and handle the pending-to-active confirmation lifecycle."
doc_version: "1"
last_updated: "2026-10-14"
---

## What it does

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](/docs/guides/alert-recipients/).) Unlike a webhook recipient, an email recipient has a confirmation step: it starts `pending` and sends nothing until the mailed confirmation link is followed.

## Set it up in the app

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](/docs/guides/alert-recipients/).

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](/_astro/email-alerts-1-recipient-status.DNwBdhkv.png)

## Do the same through the API or MCP

```bash
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](#troubleshooting)). Attach it to a monitor using the full-replacement `PUT` endpoint described in the [alert recipients guide](/docs/guides/alert-recipients/).

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.

## Plan limits

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](/docs/guides/alert-recipients/) for the recipient name length limit (255 bytes) shared by every recipient type.

## Troubleshooting

**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:

```bash
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](/docs/guides/alert-recipients/#do-the-same-through-the-api-or-mcp) 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](/docs/guides/alert-recipients/#do-the-same-through-the-api-or-mcp). 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.