# Group contacts and subscribe them together

A **contact group** bundles several contacts (mixing channels freely - email, phone, Slack, whatever) so you can
subscribe all of them to a monitor in one step, instead of adding each one individually.

## What it is and when to use it

Use a group when the same set of people or channels should hear about the same monitors: a team, an escalation
chain, or "everyone who needs to know about outages." Use individual contacts when a subscription is one-off, or
when different monitors need genuinely different mixes of contacts.

:::caution[A group is a passive preset, not a live binding]
This is the one thing worth understanding before you rely on groups: a group has **no effect by itself**.
Nothing at alert time reads group membership - adding a contact to a group does not subscribe it to anything.
A group only does something when you **apply** it to a monitor, and applying it *stamps the group's current
members onto that monitor's own subscriptions* as a one-time copy. If you later add or remove members from the
group, monitors you already applied it to keep the **old** membership - you have to apply the group to them
again to pick up the change. There is no "sync this monitor with the group" mode.
:::

## Settings reference

| Setting (UI label) | API field (v2) | Type / allowed values | Default | Plan limits | What it does for you |
|---|---|---|---|---|---|
| Group name | `name` | String, up to 100 characters | - (required) | - | Label shown wherever the group appears |
| Members | `items` | Array of `{contact, events}` - `contact` is a contact id, `events` a subset of the vocabulary below | Empty | Up to **500** members per group | The preset: which contacts, and which events each one is pre-checked for |

**Event vocabulary** (one list spans both subscription kinds, since one group can preset both at once):
`up`, `down`, `repeatedlyDown` (alert events) and `daily`, `weekly`, `monthly`, `quarterly`, `yearly` (report
frequencies). The app's own Groups editor only offers Up/Down/Repeat and Daily/Weekly/Monthly pills - Quarterly
and Yearly aren't offered as separate choices in the UI (picking Monthly there presets Monthly **and**
Quarterly **and** Yearly together, by product decision), but the API accepts all eight tokens directly if you
want finer control.

## Set it up in the app

1. Open **Alerts & Contacts** and switch to the **Groups** tab.
2. Click **Add group** and give it a name (for example "On-call team" or "Ops channel").
3. Add the contacts that belong in it, and for each one, check which events it should be pre-subscribed to when
   the group is applied.
4. Save.

To use it: when subscribing contacts to a monitor, a saved group appears alongside individual contacts. Choosing
**Apply to monitors** writes each member's preset events as ordinary subscriptions on the monitors you pick,
right now - it does not create any ongoing link between the group and those monitors.

## Do it with the API or MCP

Create a group:

```
POST /contact/group
{ "name": "On-call team", "items": [
  { "contact": "<contactId1>", "events": ["down", "up"] },
  { "contact": "<contactId2>", "events": ["down"] }
] }
```

Update it - `items`, when sent, **replaces** the whole membership snapshot (there's no per-member diff, since a
group is a snapshot):

```
PATCH /contact/group/{id}
{ "name": "On-call team (v2)" }
```

List, read, delete: `GET /contact/group`, `GET /contact/group/{id}`, `DELETE /contact/group/{id}` (deleting a
group never deletes the contacts in it).

MCP tools: `create_contact_group`, `update_contact_group`, `delete_contact_group`, `list_contact_groups`. The
members go in **`itemsJson`, a JSON array passed as a string** - there is no `items` argument:

```
create_contact_group(name="On-call team",
  itemsJson="[{\"contact\":\"<contactId1>\",\"events\":[\"down\",\"up\"]},{\"contact\":\"<contactId2>\",\"events\":[\"down\"]}]")
```

`update_contact_group(id, name, itemsJson)` replaces the whole membership when `itemsJson` is sent.

**Applying** a group to monitors has no dedicated endpoint - there is deliberately no server-side "apply". Read
the group's members and events, then write ordinary subscriptions through
[the subscription endpoints](/alerts/subscribe-monitors/#do-it-with-the-api-or-mcp) (`PUT
/monitor/{monitorId}/alert/{contactId}` per member, or the bulk diff door for many monitors at once).

To apply a group to three monitors in one call, send one `create` entry per member with that member's alert events
(report events such as `weekly` go to `POST /report/bulk` with `frequencies` instead):

```
POST /alert/bulk
{ "create": [
  { "monitorIds": ["M1", "M2", "M3"], "contactIds": ["<contactId1>"], "alertTypes": ["down", "up"] },
  { "monitorIds": ["M1", "M2", "M3"], "contactIds": ["<contactId2>"], "alertTypes": ["down"] }
] }
```

It needs both `monitor:write` and `contact:write`, and it runs in one transaction. Through MCP, send it with
`api_request(method="POST", path="/alert/bulk", bodyJson="...", confirmed=true)` - without `confirmed=true` the MCP
server refuses every `/bulk` write and sends nothing - or call `subscribe_contact` once per monitor and member.
The subscriptions are a snapshot: a contact added to the group later is not subscribed until you apply it again.

## What happens next

Creating or editing a group changes nothing about any monitor's actual alerting - it only updates the preset
itself. The moment you apply it, ordinary subscriptions are written as if you'd set them by hand; from then on
those subscriptions behave exactly like any other, including responding independently to each contact's own
alert delay and active hours.

## Limits and gotchas

- **Up to 500 members** per group; an over-limit `items` array is refused rather than silently truncated.
- **`422 validation_failed`** (reason `unknown_member`) at `/items/{i}/events/{j}` for a token outside the
  eight-word vocabulary above.
- **A patch that changes nothing is refused** (`422`, reason `empty`) - send at least `name` or `items`.
- Deleting a group only deletes the preset row; every contact that was a member keeps existing and keeps
  whatever subscriptions were already applied from it.
- Because applying is a one-time stamp, a group is not the right tool for "keep this monitor's alerting in sync
  with the team roster automatically" - there's no live link to keep in sync.

## Related

- [What a contact is](/alerts/contacts/)
- [Subscriptions: alert vs report](/alerts/subscriptions/)
- [Subscribe monitors to a contact](/alerts/subscribe-monitors/)
