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

# Users

> Read the current user and list workspace users from a custom block.

<Warning>
  Custom blocks are in private alpha:

  * Do not discuss publicly or share with anyone outside your workspace.
  * Access must be enabled per workspace. Installing the SDK does not grant access.
  * These APIs may experience breaking changes without notice.
</Warning>

## The current user

`customBlock.getCurrentUser()` and `useCurrentUser()` return the user viewing the custom block. Both read the user from the block’s state without a separate request.

Wait for `initCustomBlock()` to resolve before calling the getter or mounting components that use the hook. See [initialization](/custom-blocks/sdk/initialization).

### TypeScript API

Use `customBlock.getCurrentUser()` to read the current user in any framework. Subscribe to context changes to keep your UI updated:

```typescript theme={null}
import { customBlock, initCustomBlock } from "@notionhq/custom-blocks"

await initCustomBlock()
const user = customBlock.getCurrentUser()
console.log(user.name)

const unsubscribe = customBlock.subscribe(() => {
	const nextUser = customBlock.getCurrentUser()
	console.log(nextUser.name)
})
```

Call `unsubscribe()` when you no longer need updates. The callback can run even when the current user has not changed.

### React hook

In React, use `useCurrentUser()` to re-render when the current user changes:

```tsx theme={null}
import { useCurrentUser } from "@notionhq/custom-blocks/react"

function Greeting() {
	const user = useCurrentUser()
	return <p>Hello, {user.name ?? "there"}</p>
}
```

Both approaches return the same `NotionUser` shape.

## User object

`NotionUser` is based on the [public API User object](https://developers.notion.com/reference/user). `users.get()` and the current-user APIs return a `NotionUser`. `users.list()` returns a page of these objects. Custom blocks return only people, not bots or integrations.

All fields except `name` are always present. `name` may be omitted. `avatar_url` is present but can be `null`.

| Property | Type | Description |
| - | - | - |
| `object` | `"user"` | Identifies a user object. |
| `id` | `string` (UUID) | The user's ID. Typed as `NotionUserId` in the SDK. |
| `name` | `string` (optional) | The user's name, if available. |
| `avatar_url` | `string` (nullable) | The user's avatar URL, or `null` if no avatar is available. |
| `type` | `"person"` | Custom blocks return people. |
| `person` | `object` | The user's person details. |
| `person.email` | `string` | The user's email address. |

## List users

Each `users.list()` call returns one page of workspace users visible to the viewing user. The SDK does not fetch the remaining pages automatically.

```typescript theme={null}
import { users } from "@notionhq/custom-blocks"

const result = await users.list({ pageSize: 50 })

if (result.status === "success") {
	for (const user of result.list.results) {
		console.log(user.id, user.name, user.person.email)
	}
}
```

| Option | Description |
| - | - |
| `pageSize` | Maximum users per response. Optional integer from 1 to 100. Defaults to 100. |
| `startCursor` | Optional cursor from the previous response's `next_cursor`. Omit it for the first page. |

Pass `next_cursor` as `startCursor` to request the next page. Use the cursor exactly as returned. Do not parse it or create your own. Stop when `has_more` is false.

```typescript theme={null}
import { users, type ListUsersArgs } from "@notionhq/custom-blocks"

const args: ListUsersArgs = { pageSize: 50 }

while (true) {
	const result = await users.list(args)
	if (result.status === "error") {
		console.error(result.error)
		break
	}

	for (const user of result.list.results) {
		console.log(user.id, user.name)
	}

	if (!result.list.has_more || result.list.next_cursor === null) break
	args.startCursor = result.list.next_cursor
}
```

## Get a user

```typescript theme={null}
import { customBlock, users } from "@notionhq/custom-blocks"

// After initialization, use the current user’s ID for this example.
const userId = customBlock.getCurrentUser().id
const result = await users.get(userId)

if (result.status === "success") {
	console.log(result.user.name)
} else {
	console.error(result.error)
}
```

On success, `result.user` is a `NotionUser`.

A `people` property can contain both users and groups (`object: "group"`). `users.get()` and `users.list()` only support people. You cannot use these APIs to resolve a group or list its members.

Skip group entries when you need a person’s name and avatar. Match the person’s ID against results from `users.list()`. Reuse those results if your UI already lists workspace users. IDs in a `people` property are plain strings. `users.get()` requires a `NotionUserId`, such as an ID from the user APIs.

## Permissions

A user returned by `users.list()` does not necessarily have access to the current page or data source. Do not use this list to check page or data source permissions.

If a request returns `status: "error"`, handle the error before reading `result.user` or `result.list`. See [error handling](/custom-blocks/sdk/errors).
