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.

Return to Mailbox.