> ## 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`](/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` and `rank` 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 three fields are optional in the SDK type — read them defensively (`standing.capabilities ?? []`). Everything else (`user`, `reasons`, `title`, `metadata`) is visible to any relation.
</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
    // 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.**                                                                                       |
| `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`](/hooks/workspaces/use-fetch-workspace-members) — the whole roster
* [`useFetchWorkspaceAuthority`](/hooks/workspaces/use-fetch-workspace-authority) — the same read, but for yourself
* [Fetch Member Standing API](/api-reference/workspaces/members/fetch-member-standing)
