---
title: Contacts & groups
description: Manage notification contacts (people) and contact groups (where alerts go) — create, list, get, update and delete, with group membership in one call.
canonical: https://watchfor.io/docs/api/contacts
---

# Contacts & groups

Manage notification contacts (people) and contact groups (where alerts go) — create, list, get, update and delete, with group membership in one call.

A **contact** is a person who receives alerts; a **contact group** is the
audience alerts are routed to (monitors and alert rules point at
groups). Background: [contact groups](/docs/notifications/contact-groups).

| Method | Path | Scope | operationId |
| --- | --- | --- | --- |
| GET | `/v1/contacts` | read | `listContacts` |
| POST | `/v1/contacts` | write | `createContact` |
| GET | `/v1/contacts/{id}` | read | `getContact` |
| PATCH | `/v1/contacts/{id}` | write | `updateContact` |
| DELETE | `/v1/contacts/{id}` | write | `deleteContact` |
| GET | `/v1/contact-groups` | read | `listContactGroups` |
| POST | `/v1/contact-groups` | write | `createContactGroup` |
| GET | `/v1/contact-groups/{id}` | read | `getContactGroup` |
| PATCH | `/v1/contact-groups/{id}` | write | `updateContactGroup` |
| DELETE | `/v1/contact-groups/{id}` | write | `deleteContactGroup` |

## Contacts

The contact object:

```json
{
  "id": "9ffb8d6d-…",
  "object": "contact",
  "name": "Jane Ops",
  "email": "jane@example.com",
  "phone": "+3706…",
  "groups": [ { "id": "391e64ad-…", "name": "On-Call" } ],
  "created_at": "2026-08-24T16:00:00.000Z",
  "updated_at": "2026-08-24T16:05:00.000Z"
}
```

### List contacts

`GET /v1/contacts` — newest first, cursor-paginated (`limit` 1–100,
`cursor` from `next_cursor`; any other `limit`, or a `sort` parameter,
returns `400`). Cursors are positions, so a page stays stable even if the
contact a cursor pointed at was deleted meanwhile.

```bash
curl https://watchfor.io/api/v1/contacts \
  -H "Authorization: Bearer wf_live_YOUR_KEY"
```

### Create a contact

`POST /v1/contacts` — requires `write` scope.

| Field | Required | Notes |
| --- | --- | --- |
| `name` | yes | 1–100 characters |
| `email` | yes | Unique per organization, case-insensitively |
| `phone` | no | Up to 30 characters |
| `groupIds` | no | Up to 50 [contact group ids](#contact-groups) to add the contact to right away |

```bash
curl -X POST https://watchfor.io/api/v1/contacts \
  -H "Authorization: Bearer wf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Jane Ops", "email": "jane@example.com", "groupIds": ["391e64ad-…"] }'
```

Returns `201` with the contact. A duplicate email returns
`409 conflict`; the plan's contact limit returns `403`. Supports
[`Idempotency-Key`](/docs/api/errors#idempotency--safe-retries).

### Get, update, delete a contact

`GET /v1/contacts/{id}` · `PATCH /v1/contacts/{id}` ·
`DELETE /v1/contacts/{id}` (write scope for PATCH and DELETE).

PATCH is partial — send only what changes: `name`, `email`, `phone`
(`null` clears it), `groupIds`. Omitting `groupIds` leaves memberships
unchanged; `[]` removes the contact from every group; any other list
**replaces** all memberships.

```bash
curl -X PATCH https://watchfor.io/api/v1/contacts/9ffb8d6d-… \
  -H "Authorization: Bearer wf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+3706…", "groupIds": [] }'
```

`DELETE` removes the contact from every group and returns `200` with
`{ "object": "deleted", "id": "…", "deleted": true }`.

## Contact groups

The contact group object (the member list is included on
`GET /v1/contact-groups/{id}` and on create/update responses):

```json
{
  "id": "391e64ad-…",
  "object": "contact_group",
  "name": "On-Call",
  "description": null,
  "is_default": true,
  "member_count": 3,
  "members": [ { "id": "9ffb8d6d-…", "name": "Jane Ops", "email": "jane@example.com" } ],
  "created_at": "2026-07-01T08:00:00.000Z",
  "updated_at": "2026-08-24T16:05:00.000Z"
}
```

`is_default` marks the organization's default group — the one new
monitors notify unless told otherwise.

### List groups

`GET /v1/contact-groups` — newest first, cursor-paginated; items carry
`member_count` but not `members`.

### Create a group

`POST /v1/contact-groups` — requires `write` scope. Body: `name`
(required, 1–100, unique per organization), `description` (up to 500),
`contactIds` (up to 1000 contact ids to add as members — every id must be
a contact of your organization, otherwise `400` listing the unknown ones:
`contactIds: unknown contact id(s) in this organization: …`). Returns
`201`; a duplicate name returns `409`; the plan's group limit returns
`403`. Supports `Idempotency-Key`.

```bash
curl -X POST https://watchfor.io/api/v1/contact-groups \
  -H "Authorization: Bearer wf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Platform team", "contactIds": ["9ffb8d6d-…"] }'
```

### Get, update, delete a group

`GET /v1/contact-groups/{id}` · `PATCH /v1/contact-groups/{id}` ·
`DELETE /v1/contact-groups/{id}` (write scope for PATCH and DELETE).

PATCH is partial: `name`, `description` (`null` clears), `contactIds` —
omitted keeps members, `[]` empties the group, any other list replaces
the full member list (unknown ids are `400`, as on create).

`DELETE` refuses the **default** group with `409` (make another group
the default in the dashboard first). A group that is **still in use** —
by alert rules (`contactGroupId`), by monitors' notification groups or by
a channel's routing — also returns `409 conflict`, naming what uses it
("still used by 1 alert rule(s), 2 monitor(s)"). Add `?force=true` to
delete it anyway: the references are removed, affected alert rules fall
back to their monitor's notification groups, and the
[activity log](/docs/api/activity) entry records `forced: true`.

```bash
curl -X DELETE "https://watchfor.io/api/v1/contact-groups/391e64ad-…?force=true" \
  -H "Authorization: Bearer wf_live_YOUR_KEY"
```

Wiring groups to notification channels and to on-call escalation
policies stays in the dashboard — see [Notifications](/docs/notifications)
and [On-call](/docs/alerting/on-call).

## Also via

MCP tools `list_contacts`, `get_contact`, `create_contact`,
`update_contact`, `delete_contact`, `list_contact_groups`,
`get_contact_group`, `create_contact_group`, `update_contact_group`,
`delete_contact_group`.

---

Canonical page: https://watchfor.io/docs/api/contacts · All docs: https://watchfor.io/docs · Site guide: https://watchfor.io/llms.txt
