Project members and capabilities
Project membership controls access to that project's mail and logs. Use
canonical principal UUIDs, rather than usernames, client IDs, or native
organization IDs. Obtain membership IDs from the current project-member
list. Every request uses the selected workspace, authenticated
POST JSON, and a project_id.
Read members
POST /projects/members/list requires project.member.list and accepts
project_id, optional limit (integer 1–100, default 50), and optional
offset (integer 0–1,000,000, default 0).
{"project_id":"<project-uuid>","limit":50,"offset":0}
The response data contains project_id, group, caller_role,
available_roles, active_owner_count, roles, members, total_count,
limit, and nullable next_offset. Continue at next_offset until it is
null. The group describes the pinned Management group.
Each member includes member_id, principal_id, role, status, timestamps,
and a nullable principal display summary (name, kind, status). The
response also supplies is_self, final_owner, can_leave, can_update,
can_remove, allowed_roles, allowed_statuses, can_edit_capabilities,
capabilities_mode, and capability_tag_ids. Use these current controls
instead of deriving buttons from display labels. service_access describes
the target's elevated service role; it does not grant project authority.
Add, save, remove, and leave
| Route | Fields after project_id |
Required action |
|---|---|---|
/projects/members/add |
Required principal_id |
project.member.add |
/projects/members/save |
Required principal_id; optional member_id, role, status |
project.member.save |
/projects/members/remove |
Required principal_id and member_id |
project.member.remove |
/projects/members/leave |
No other identity or membership fields | project.member.leave |
Add creates an ordinary active Member for a target that already has active
Mailbox service access. It accepts no caller-supplied role or status. It
returns the membership's id, principal, role, and status. An existing
membership causes 409; edit it explicitly.
Save creates a membership when member_id is omitted; a new membership
defaults to role: "member", status: "active". To edit an existing
membership, send its exact ID. Omitted role/status preserve existing state.
Allowed role values are owner, admin, and member; editable statuses are
active and disabled. New or activated targets must have active service
access. Existing membership identity and principal must match. Changing a
role clears prior custom capability selections and restores role defaults.
{
"project_id":"<project-uuid>","principal_id":"<principal-uuid>",
"member_id":"<membership-uuid>","status":"disabled"
}
Owners can manage all project roles. Admins can create or manage only Members;
they cannot promote, disable, or remove an Owner/Admin. Role changes and
privileged-target changes also require project.member.assign_roles.
Removing, disabling, demoting, or leaving as the last active Management
Owner fails with 409. Add another active Owner before transferring that
responsibility.
Save returns saved: true; remove returns removed: true. Both include
project_id, a member result with membership/principal identity, and
context. Save's member result also has role and status. context may be
null after a successful self-demotion or removal revokes subsequent access.
Removal deletes the membership and its capability assignments. Leave removes
only the current effective principal's membership and returns
{"left":true,"project_id":"<project-uuid>"}. It rejects identity,
membership, role, or status fields for another target.
Read and save capability selections
POST /projects/members/capabilities/list accepts only project_id and
requires project.member.list. It returns project_id, read_only: true,
tags, and roles. Each tag has tag_id, exact capability, name, and
description. Each role describes default_tag_ids, allowed_tag_ids,
protected_capabilities, and catalogue version with configuration metadata.
POST /projects/members/capabilities/save requires an Owner/Admin with
project.member.save and accepts exactly:
{
"project_id":"<project-uuid>","principal_id":"<principal-uuid>",
"member_id":"<membership-uuid>","mode":"custom","tag_ids":[]
}
mode is defaults or custom. Both require tag_ids as a JSON array.
For defaults, supply an empty array to use current role defaults. For
custom, select distinct returned tag UUIDs allowed for that target role;
an empty selection grants no optional actions. Protected membership rights
remain. Organization grants can further restrict all effective rights.
Admins can edit only Member capability selections.
Optional project actions include mail.send, mail.log.search, and
mail.log.view; Members may also receive project.member.list. Discover
current defaults and selections rather than hardcoding them. Save returns
saved: true, project_id, and the caller's refreshed context.
GET /capabilities.json returns the service's capability document without
the business-response envelope. It includes schema_version,
catalogue_version, families, capabilities, presets, and
role_defaults, with descriptive metadata. No access token is required.
The document describes possible actions; it does not grant them or identify
the current caller's effective permissions. Unavailable catalogue data can
return 503 in the ordinary failure envelope.