Skip to main content
Update Member
Edits a member, with two capability tiers by field sensitivity:
  • Powerful fields (capabilities, permissions, and rank — as either rank or relativeRank) require edit-member-access, plus the rank rule and the no-escalation guard.
  • Cosmetic fields (title, metadata) require only edit-member-profile. A member editing their own title needs no capability.
Rank moves in either coordinaterank (absolute) or relativeRank (an offset from the actor) — and they are mutually exclusive; sending both is a 400. Omitting both means rank unchanged: unlike Create Invite, this endpoint has no value default, so editing someone’s capabilities never moves them on the ladder. See choosing a rank. Grant vs strip asymmetry: you may only add a capability/permission you hold on the target node (resolved set, including via reach); stripping is governed by rank alone. Cross-node rank is not compared — the rank guard runs only when actor and target share a member row on the same workspace.

Path Parameters

string
required
The workspace UUID.
string
required
The target member’s user id.

Body Parameters

All optional; the controller enforces which tier each touched field belongs to. At least one must be provided.
string[]
New capability set (powerful — edit-member-access).
string[]
New permission set (powerful — edit-member-access).
number
New absolute rank, 02147483647 (powerful — edit-member-access + rank rules). Mutually exclusive with relativeRank. Omitting both leaves rank unchanged.
number
New rank expressed as an offset from the acting user: 1 = one rung below me. Must be 121474836470 (a peer) and negatives are a 400. The resolved value is bounded too, so an in-range offset that overflows once anchored is a 400, not a 500. Mutually exclusive with rank, and with no default: omitting both leaves rank unchanged.Anchored on the actor’s own rank if they hold a member row on this workspace, apex (one step above rank 0) otherwise — the anchor turns on the row, not on what kind of actor they are. Resolved to an absolute number at write time and stored absolute; it is a snapshot and does not follow the actor’s own rank afterwards.Because an in-ladder anchor is >= 0 and the offset is >= 1, a direct-member actor can never reach rank 0 this way — and neither can they by naming absolute rank: 0, which the assign rule below refuses for exactly the same reason (nothing is strictly below 0). There is no separate rank-0 guard: rank 0 is effectively owner-only because the owner skips the rank block, not because a check names them. An actor with no member row here — an ancestor owner, or a cross-node reach holder — also skips it.A service/master key is not on that list. Unlike Create Invite, this route has no unbounded path: actingUserId is required, so a key is always somebody, and it faces exactly the floors that somebody faces. A key that names nobody does not skip the guard — it gets a 400 workspace/missing-user-id.
string
New cosmetic title (edit-member-profile, or self for own title). Nullable.
object
New cosmetic metadata (edit-member-profile).
string
required
Service/master keys only — the acting user (sent in the body; the path :userId is the target). Required for a key: this route has no unbounded path, so a key that names nobody is refused with 400 workspace/missing-user-id. Every check below — the two capability tiers, the rank guard, the assign rule and no-escalation — runs against the named user. Act as the owner for an unrestricted edit.A plain user token omits it — the actor is the token’s own user. The field is not ignored for such a token: sending your own user id is a harmless no-op, but sending anyone else’s is a 403 workspace/unauthorized. See Acting on behalf of a user.

Response

Returns the updated WorkspaceMember object.

Error Responses

One message per tier, depending on which fields the request touched. Powerful fields (capabilities, permissions, rank, relativeRank):
Cosmetic fields (title, metadata) — not raised when a member is editing only their own title. Editing your own metadata still requires edit-member-profile:
Two distinct messages share this code. The act rule, on the target:
…and the assign rule, on the rank you asked for — checked against the resolved absolute value, so rank and relativeRank face it identically. This is also what refuses rank: 0 to anyone holding a row on this workspace:
Checked after the offset is resolved. Out-of-range rank / relativeRank input is refused earlier by the schema, with the same code.
A schema rejection, so the message is prefixed with the field it was reported against.
The offending values are named. Capabilities:
…and permissions:
Only added values are checked — removing a capability or permission is governed by rank alone.
A service/master key called this route without naming an actingUserId. Every gate on this route is measured against the editor’s own standing, so the edit must be performed as somebody — act as the owner for an unrestricted edit.
A plain user token sent an actingUserId naming a different user. Only a service/master key may act as someone else.
Every path id on the workspaces bundle is checked for UUID shape before the route runs, so a malformed one is a plain 400 rather than a 500 from the database.