---
title: "Update Coverage Members"
method: PUT
path: "/scheduling/coverage-groups/{group_id}/members"
tags: ["scheduling"]
---

# Update Coverage Members

`PUT /scheduling/coverage-groups/{group_id}/members`

## Request

- Base URL: `https://api.verdun.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.verdun.ai/scheduling/coverage-groups/{group_id}/members`
- Auth: HTTP bearer

Replace this coverage group's standing members.

COVERAGE GROUPS CONFER SCOPE, NEVER PERMISSION. A member sees every site
this group's grants cover -- off-shift included, because a manager
reviewing last night must see the same sites they cover -- and gains no
capability whatsoever; theirs remain exactly their role's. Shift seating is
a separate thing: it says who is on the desk when, and confers nothing.

The user-side mirror is `PUT /operator/{id}/coverage-groups`; both write
through the two ends of one relationship and share their rails.

Replace-all: the list sent IS the membership, and `[]` clears it (which is
also how a group is prepared for deletion -- deleting one with members is
refused with a 409). 409 for a structurally scoped operator (site_manager /
account_manager / location_manager) or an unconfined one (owner / monitoring_manager)
anywhere in the list; 404 for
an unknown group or operator id.

## Path parameters

- `group_id` string, required

## Request body

- UpdateCoverageMembersRequest: Replace-all: the group's members become exactly this list. Sending `[]` clears the group, which is also how a group is prepared for deletion (deleting a group with members is refused with a 409 -- a revoked grant must not vanish silently). MEMBERSHIP CONFERS SCOPE, NEVER PERMISSION. A member sees the sites this group's grants cover, off-shift included; their capabilities stay exactly their role's. Structurally scoped roles (site_manager, account_manager, location_manager) and unconfined ones (owner / monitoring_manager) are refused with a 409 -- the first because their scope is derived and not editable as a grant, the second because their scope is unrestricted and the row would be permanently inert.
  - `operator_ids` string[], required: The operators who are standing members of this group. Replace-all: operators omitted here lose the group's site access at their next scope resolution (on an open SSE stream, within 30 seconds).

## Response `200`

Successful Response

- UpdateCoverageGroupResponse
  - `group` CoverageGroupModel, required
    - `id` string, uuid, required: The coverage group ID.
    - `name` string, required: Display name of the group.
    - `color` string, required: Display color used in schedule grids and chips.
    - `grants` CoverageGrantModel[], required: The parent/site grants that define the group's sites.
      - `id` string, uuid, required: The grant ID.
      - `parent_id` string, uuid, nullable: Parent granted wholesale - covers every current AND future site under it (null for site grants).
      - `site_id` string, uuid, nullable: Individually granted site (null for parent grants).
    - `site_count` integer, required: Distinct sites currently covered (parent grants expanded).
    - `members` CoverageGroupMemberModel[]: Operators who are standing members of this group. Their tenant scope includes this group's sites -- SCOPE ONLY, never a permission. Deleting a group with members is refused (409).
      - `id` string, uuid, required: The operator ID.
      - `first_name` string, required: Member's first name.
      - `last_name` string, required: Member's last name.
      - `role` 'owner' | 'operator' | 'site_manager' | 'read_only' | 'account_manager' | 'monitoring_manager' | 'location_manager' | 'support', required
    - `member_count` integer: How many operators are standing members of this group.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/verdun/apis/verdun-api.md) - [All operations](https://skmtc.dev/verdun/apis/verdun-api/llms.txt) - [OpenAPI document](https://skmtc.dev/verdun/apis/verdun-api/revisions/35a2a6ebedda?raw)
