workspaces module is the developer’s authorization-server SDK for the Workspaces bundle. It exposes the full surface: workspace CRUD, membership management, the invitation lifecycle, and the service-key authority read you use to make your own app-level decisions.
Requires the
workspaces bundle. See Bundles to install it. Because this is a service-key SDK, most calls take an explicit userId — the user the action is performed as (the service key can act as any user). For fetchWorkspaceAuthority, userId is the target whose standing to resolve.This SDK is not required in order to manage workspaces. All 21 endpoints are equally available to a browser or mobile app through the
@sublay/core hooks and @sublay/js, acting as the signed-in user and subject to the same ownership / capability / rank rules. What the node SDK adds is the actor userId — performing an action as some other named user — which only a service/master key may do.Workspace lifecycle
createWorkspace
create-sub-workspace capability on the parent; the creator becomes the child’s owner.
string
required
The user the workspace is created as (becomes the owner).
string
required
Display name (1–100 characters).
object
Opaque developer data.
string
Parent for child creation; absent/
null → root.fetchWorkspace
string
required
The workspace UUID.
string
Comma-separated include flags;
memberCount adds the direct member count.fetchManyWorkspaces
Lists a user’s direct-membership + owned workspaces (paginated).string
required
The user whose workspaces to list.
number
number
string
updateWorkspace
edit-workspace or owner). Does not flip the inherit flag.
string
required
string
required
The acting user.
string
object
updateWorkspaceInheritFlag
string
required
string
required
Must be own owner or an ancestor owner.
boolean
required
deleteWorkspace
workspace.deleted per deleted workspace — and no workspace.member.removed events for the memberships it tears down (see Webhooks).
string
required
string
required
Must be own owner or an ancestor owner.
transferWorkspaceOwnership
string
required
string
required
The acting user (own owner or ancestor owner).
string
required
The new owner (any verified user).
string
"demote" or "remove".number
On demote; defaults to
0.string[]
Membership
fetchWorkspaceMembers
Returns the unified roster (WorkspaceRosterResponse), or WorkspaceRosterCountsResponse when countOnly is set.
The roster fences the authority-bearing reason fields (
rank, capabilities, permissions) from callers who cannot manage people on the workspace. A service key is never fenced — it always sees them — so this only matters for the client-side and hook surfaces. The SDK types mark the three fields optional for that reason.string
required
string
ancestorOwners, reachHolders, descendants.boolean
fetchWorkspaceMemberStanding
string
required
string
required
The user whose standing to read.
WorkspaceMemberStanding. On its user field only id is guaranteed (WorkspaceStandingUser): the server returns the full user record when the user row still exists and falls back to { id } alone when it does not — a deleted user with a lingering membership row is a reachable case. Read the rest defensively (standing.user.username ?? "Deleted user").
reasons is an array of structured { type, viaWorkspaceId? } entries — the same shape a roster entry’s reasons carries — so you learn not just the kind of standing but which ancestor grants it. capabilities / permissions / rank are typed optional because the server omits them for callers who cannot manage people; a service key is never fenced, so they are always present on this SDK’s responses.
updateWorkspaceMember
edit-member-access + rank rules + no-escalation; cosmetic fields require edit-member-profile.
string
required
string
required
The member being edited (path).
string
required
The acting user (body).
string[]
string[]
number
string
object
removeWorkspaceMember
remove-member (rank-bounded); sole-owner protected.
string
required
string
required
The member to remove.
string
required
The acting user.
leaveWorkspace
string
required
string
required
The user leaving.
removeWorkspaceMemberFromSubtree
409 workspace/owns-descendants (and a report) if the target owns any descendant workspace.
skippedCount is 0 from this SDK. The sweep is partial only for a non-owner actor, and a service key reaches the whole subtree via the god-path regardless of which acting userId you name — so a server-side sweep always clears every descendant. The field is part of the shared response shape (see the browser SDK and the hook, where a non-owner actor can get a partial sweep). Assert on it anyway if you proxy this call on behalf of an end user, rather than assuming removedCount means the user is fully offboarded.string
required
string
required
The user to offboard.
string
required
The acting user.
Invitations
createWorkspaceInvite
invite capability. Here userId/username (if used) address the invite target; the inviter is the service-key subject. Email matching against existing accounts is case-insensitive.
string
required
string
One of
email/userId/username.string
Invite target user id.
string
Invite target username.
string[]
string[]
number
required
string
fetchWorkspaceInvites
invite (or owner). Not to be confused with fetchMyWorkspaceInvites, which is one user’s inbox of invites addressed to them across every workspace.
revokeWorkspaceInvite
resendWorkspaceInvite
409. Returns the refreshed WorkspaceInvitation, carrying the new expiresAt. Like createWorkspaceInvite, it requires workspaces.inviteAcceptUrl on the project → otherwise 409 workspace/missing-invite-accept-url with expiresAt untouched.
acceptWorkspaceInvite
string
required
string
required
The accepting user (must be the target and verified).
declineWorkspaceInvite
userId you act as must itself be verified, or the call returns 403 workspace/email-not-verified.
fetchMyWorkspaceInvites
userId). The per-workspace outbox counterpart is fetchWorkspaceInvites.
Authority-as-a-service
fetchWorkspaceAuthority
The service-key authority read — the crux of the server-side surface. Resolve any user’s standing on a workspace, then run your own permission check with a one-line.includes().
string
required
string
required
The target user whose resolved standing to read.
reasons entries carry viaWorkspaceId on ancestor-owner / reach-holder, naming the ancestor responsible — so when a user has authority you did not expect, you can tell exactly which node to go fix. capabilities is the fully-resolved set, and view is implied by every other capability: any user with standing carries it, while a user with no relation at all comes back with reasons: [] and an empty capability set.
Sublay never consumes your opaque permissions — there is deliberately no ?permission= check or can() helper.
