---
title: "Choose who gets alerts"
description: "Attach and detach recipients on a monitor, understand the full-replacement API semantics, and what happens to queued deliveries when you do."
doc_version: "1"
last_updated: "2026-10-14"
---

## What it does

A recipient is a destination for alerts, created once at the account level and then attached to any number of monitors. Each monitor has its own set of attached recipients; attaching or detaching a recipient from one monitor doesn't affect its attachment to any other monitor. The dashboard supports creating **webhook** and **email** recipients today. um-api also accepts `type: "slack"` and `type: "pagerduty"` recipients directly through `POST /api/v1/recipients` — each takes its own native configuration (a Slack incoming-webhook URL, or a PagerDuty Events API v2 routing key) and needs no relay. Their own dashboard UI hasn't shipped yet (reserved slugs `slack-alerts` and `pagerduty-alerts` for their guides, once that ships), so create either one directly through the API if you need it today.

**Never attach a Slack or PagerDuty destination to a `type: "webhook"` recipient.** UptimeMonitoring's webhook payload (`event`, monitor fields, delivery metadata — see [Webhooks](/docs/webhooks/#payload-format)) isn't the shape either destination expects: Slack silently discards it, and PagerDuty's Events API rejects it outright. For a destination with no native recipient type (Discord, Pushover, ntfy, and others), use the open-source [alert-bridge](/docs/alert-bridge/) relay instead of pointing a webhook recipient's URL directly at it.

## Set it up in the app

### Create an account-level recipient

1. Go to **Recipients** in the dashboard and click **Create recipient**.
2. Choose **Webhook** or **Email**, fill in the URL or email address, pick which events to notify on (**Down**, **Up**, **Flapping**), and optionally turn on **Default for new monitors**.
3. Click **Create recipient**.

For a webhook recipient, you'll see **Your recipient secret** once — copy it now, since UptimeMonitoring won't show it again. For an email recipient, you'll see **Confirmation sent to `<address>`** — alerts don't start until that confirmation is followed (see the [email alerts guide](/docs/guides/email-alerts/) for that lifecycle).

### Attach or detach recipients on a monitor

1. Open the monitor and find its **Recipients** section.
2. Check or uncheck recipients, then click **Save**.

![A monitor's Recipients section in the dashboard, with several recipients checked and a Save button](/_astro/alert-recipients-1-recipients.B323QTgq.png)

If no recipient ends up attached and the monitor is enabled, the dashboard shows "No one is listening to this monitor" — a safety check that the monitor isn't silently unmonitored by a human.

## Do the same through the API or MCP

**`PUT /api/v1/monitors/{monitorID}/recipients` replaces the monitor's complete recipient set — it is not a merge.** Sending just a new recipient's id detaches every other recipient currently attached to that monitor. Always read the current set first, add to it, and submit the full result:

```bash
# 1. Read the monitor's current recipients
CURRENT=$(curl -s https://api.uptimemonitoring.com/api/v1/monitors/1287/recipients \
  -H "Authorization: Bearer $UPTIMEMONITORING_API_KEY")
# -> {"recipients": [{"id": 10, "down_delay_s": 60}, {"id": 11, "down_delay_s": 0}]}

# 2. Build the full set from what the GET actually returned — append the
#    new recipient (42) to .recipients rather than retyping it, so existing
#    attachments and their down_delay_s survive even if the current set
#    wasn't what you expected. The structured "recipients" form is what
#    lets you set the new recipient's own down_delay_s in the same call
#    (an already-attached pair keeps its delay either way). Requires jq.
BODY=$(echo "$CURRENT" | jq '{recipients: (.recipients + [{id: 42, down_delay_s: 0}])}')
curl -X PUT https://api.uptimemonitoring.com/api/v1/monitors/1287/recipients \
  -H "Authorization: Bearer $UPTIMEMONITORING_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$BODY"
```

**This read-then-write sequence has no concurrency protection.** The `PUT` carries no version, ETag, or `If-Match` precondition, so two clients that each read the same list and then submit their own addition can race: whichever `PUT` lands second silently overwrites the first, and the recipient the first client added is detached again — along with that recipient's queued deliveries. Edit a monitor's recipients from one place at a time, and re-read the result after saving to confirm it matches what you intended.

Creating a monitor can also attach recipients directly, through `create_monitor`'s `recipient_ids` or `recipients` arguments (mutually exclusive — specifying both is an error); `recipients` additionally lets you set a per-recipient `down_delay_s`. There's no MCP tool for changing an existing monitor's recipients after creation — `update_monitor` doesn't take a recipients argument — so use the REST `PUT` endpoint above, or the dashboard, for that. See [Use UptimeMonitoring through MCP](/docs/mcp/).

For creating a webhook recipient directly through the API, and its payload format and signature verification once it's attached, see [Webhooks](/docs/webhooks/#create-an-account-level-webhook-recipient).

### Detaching a recipient vs. deleting it

Detaching a recipient from one monitor (an updated `PUT` that no longer includes its id) deletes only that monitor's own queued (`pending`/`retrying`) deliveries for that recipient — its attachment to any other monitor, and that monitor's own queued deliveries, are untouched. A delivery a worker already claimed just before the detach commits can still complete; whether it's recorded in the delivery log afterward depends on which operation's database write lands first, so you may or may not see it in the log either way.

Deleting the account-level recipient (`DELETE /api/v1/recipients/{recipientID}`) cascades: it detaches the recipient from every monitor that referenced it, and deletes only its pending/retrying deliveries across all of them, the same way a single detach would — just applied everywhere at once. Completed, failed, and superseded delivery history for that recipient survives the deletion; it ages out later under the account's delivery-log retention window (see [Webhooks](/docs/webhooks/)), and those historical rows can keep referencing the now-deleted recipient's id.

## Plan limits

A recipient name is capped at 255 bytes (`recipientNameMaxLen` in um-api's `internal/api/recipients.go`), enforced on the raw bytes before UTF-8 validity is checked — not 255 characters. A name using non-ASCII characters (for example, emoji or CJK text) reaches that ceiling at fewer characters than 255.

See [Monitors](/docs/monitors/) for monitor count caps, and [Webhooks](/docs/webhooks/) for the account-wide delivery log and retry policy shared by every recipient type.

## Troubleshooting

**My `PUT` detached recipients I didn't mean to remove.** You (or another client) submitted a partial recipient set. `PUT` always replaces the complete set — read the current set first, then submit the full list with your change included, as shown above.

**A teammate's change to a monitor's recipients disappeared.** Two edits raced: both of you read the same list, each added something different, and the second `PUT` to land won, overwriting the first's addition. There's no built-in locking for this — coordinate changes to one monitor's recipients from one place at a time, and re-read after saving.

**A recipient got detached and I still see a delivery for it afterward.** That's the documented race: a delivery a worker had already claimed right before the detach can still complete and get recorded, even though the detach already ran. This is expected, not a bug.

**I deleted a recipient and its old deliveries still show up.** Deleting a recipient removes only its pending/retrying deliveries. Completed, failed, and superseded history survives until it ages out under the retention window — it isn't erased on delete.