> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sublay.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Fetch workspace member standing

> One user's full resolved standing on a workspace, addressed by userId

## Overview

`useFetchWorkspaceMemberStanding` returns a callable that reads a single user's full standing on a workspace, addressed by **user id** (not a membership-row id, so it works even for users with no direct row). It returns the same unified shape as one roster row, computed on demand for **any** relation — direct `member`, this workspace's `owner`, an `ancestor-owner`, or a `reach-holder`.

**Authorization:** requires roster visibility on the workspace — **any relation** (owner, ancestor-owner, member, reach-holder), the same gate as [`useFetchWorkspaceMembers`](/v8/hooks/workspaces/use-fetch-workspace-members). The signed-in user is the actor; `targetUserId` names **who is being read**, not who is asking.

<Warning>
  **`capabilities`, `permissions`, `rank` and `relativeRank` are fenced.** They are **omitted from the response** (absent — not `null`) unless the signed-in user holds one of the four people-operating capabilities on this workspace (`invite`, `remove-member`, `edit-member-access`, `edit-member-profile`), is the `owner` / an `ancestor-owner`, or is reading **their own** standing. The gate is scoped to **this** workspace — it is a per-node verdict, and your resolved standing here includes what reaches in from an open inherit chain but not what a **sealed** boundary blocks. The four fields are optional in the SDK type — read them defensively (`standing.capabilities ?? []`). Everything else (`user`, `reasons`, `title`, `metadata`) is visible to any relation. `relativeRank` is fenced *with* `rank`, not beside it: it is `rank` minus your own anchor, a number you already know, so leaking it would leak `rank` exactly.
</Warning>

## Usage Example

```tsx theme={null}
import { useFetchWorkspaceMemberStanding } from "@sublay/react-js";

function MemberDetail({
  workspaceId,
  targetUserId,
}: {
  workspaceId: string;
  targetUserId: string;
}) {
  const fetchWorkspaceMemberStanding = useFetchWorkspaceMemberStanding();

  const load = async () => {
    const standing = await fetchWorkspaceMemberStanding({
      workspaceId,
      targetUserId,
    });
    // { user, reasons, title, metadata } — plus capabilities/permissions/rank/relativeRank
    // when you may see them (see the fencing warning above).
  };
}
```

## Parameters

<ParamField path="workspaceId" type="string" required>
  The workspace UUID.
</ParamField>

<ParamField path="targetUserId" type="string" required>
  The **target** user whose standing to read — a path param, not an acting user.
</ParamField>

## Returns

`WorkspaceMemberStanding`:

| Field | Type | Description |
| - | - | - |
| `user` | `WorkspaceStandingUser` | The target user. Normally the full user record, but **only `id` is guaranteed** — see the note below. |
| `reasons` | `WorkspaceAuthorityReasonDetail[]` | Why the user has standing — structured `{ type, viaWorkspaceId? }` entries. `viaWorkspaceId` names the granting ancestor and appears on `ancestor-owner` / `reach-holder` only. |
| `capabilities` | `string[]?` | The **resolved** capability set (direct + reach + ownership). **Fenced** — see the warning above. **`view` is implied by every other capability**, so anyone with standing carries it. |
| `permissions` | `string[]?` | **Per-node** permissions (direct membership on this workspace only; may be empty). **Fenced.** |
| `rank` | `number \| null` (optional) | Direct-membership rank, or `null` for owners / ancestor-owners / reach-only holders. **Fenced.** |
| `relativeRank` | `number \| null` (optional) | The target's position as an **offset from you**: `2` = two rungs below you, `-3` = three rungs *above* you, `0` = your peer. `null` exactly when `rank` is. Your own anchor is your member row here if you hold one, apex otherwise. **Fenced** with `rank`. |
| `title` | `string \| null` | Cosmetic title. |
| `metadata` | `Record<string, any>` | Opaque member metadata. |

<Note>
  **Only `user.id` is guaranteed.** 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. The SDK type reflects this: `id` is required and every other field is optional, so read the rest defensively (`standing.user.username ?? "Deleted user"`).
</Note>

## Error codes

| Code | Status | Meaning |
| - | - | - |
| `workspace/unauthorized` | 403 | You cannot see this workspace's roster. |
| `workspace/not-found` | 404 | No such workspace in this project. |

## Related

* [`useFetchWorkspaceMembers`](/v8/hooks/workspaces/use-fetch-workspace-members) — the whole roster
* [`useFetchWorkspaceAuthority`](/v8/hooks/workspaces/use-fetch-workspace-authority) — the same read, but for yourself
* [Fetch Member Standing API](/v8/api-reference/workspaces/members/fetch-member-standing)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.