When to Use
- Workspace member directory: Build a team directory by listing all person-type users, extracting their names and emails, and syncing the list to an HR system or a contact database.
- User picker population: At workflow startup, load all workspace members to populate a dropdown in an admin tool or BizFirst Form so users can select assignees by name instead of by UUID.
- HR system sync: Periodically compare Notion workspace members against an HR system's active employee list to identify discrepancies — for example, former employees still having workspace access.
- Integration access audit: List all users including bots to identify which integrations have workspace access. Compare against an approved integration list for security compliance.
- Name-to-ID resolution: When an external system provides a user's name rather than a Notion UUID, call
user/getMany and find the match by name to resolve the user ID for subsequent page/update property assignments.
Configuration
Authentication
| Field | Required | Description |
AuthenticationMethod | Required | "ApiToken" or "OAuth2". |
ApiToken | Required | Notion Internal Integration Token starting with secret_. |
ClientId | OAuth2 | OAuth2 client ID. |
ClientSecret | OAuth2 | OAuth2 client secret. |
AccessToken | OAuth2 | OAuth2 access token. |
Operation Fields
| Field | Required | Description |
ReturnAll | Optional | When true, automatically pages through all users. Default: false. |
Limit | Optional | Max users to return per call (1–100). Default: 100. |
StartCursor | Optional | Pagination cursor from a previous call's next_cursor. |
Sample Configuration
{
"resource": "user",
"operation": "getMany",
"AuthenticationMethod": "ApiToken",
"ApiToken": "{{ $credentials.notionApiToken }}",
"ReturnAll": true
}
Validation Errors
| Error Code | Cause |
NOTION_UNAUTHORIZED | API token is invalid or disconnected from workspace. |
NOTION_INVALID_CONFIG | Limit is outside the valid range (1–100). |
NOTION_INVALID_REQUEST | StartCursor is not a valid pagination cursor. |
NOTION_RATE_LIMITED | Rate limit exceeded. |
Output
Success Port
| Field | Type | Description |
results | array | Array of user objects. Each contains id, name, email, avatarUrl, and type ("person" or "bot"). |
has_more | boolean | Whether additional users exist past the current page. |
next_cursor | string | Pagination cursor for the next call. Null when has_more is false. |
Error Port
On failure the error port receives errorCode, message, and httpStatus.
Sample Output
{
"results": [
{
"id": "a1b2c3d4-1111-2222-3333-e5f678901234",
"name": "Sarah Chen",
"email": "sarah.chen@acmecorp.com",
"avatarUrl": "https://s3.us-west-2.amazonaws.com/secure.notion-static.com/avatars/sarah.jpg",
"type": "person"
},
{
"id": "b2c3d4e5-2222-3333-4444-f6a789012345",
"name": "Marcus Johnson",
"email": "marcus.johnson@acmecorp.com",
"avatarUrl": null,
"type": "person"
},
{
"id": "c3d4e5f6-3333-4444-5555-a7b890123456",
"name": "BizFirstAI Integration",
"email": null,
"avatarUrl": null,
"type": "bot"
}
],
"has_more": false,
"next_cursor": null
}
Expression Reference
| Expression | Type | Use |
{{ $output.getManyUsers.results.length }} | number | Total user count including bots |
{{ $output.getManyUsers.results.filter(u => u.type === 'person').length }} | number | Count of human users only |
{{ $output.getManyUsers.results.find(u => u.name === 'Sarah Chen').id }} | string | Resolve name to UUID for use in page/update assignee |
{{ $output.getManyUsers.results.filter(u => u.type === 'person').map(u => u.email) }} | array | All person emails for bulk notification |
{{ $output.getManyUsers.has_more }} | boolean | Gate manual pagination loop |
Node Policies & GuardRails
| Policy | Detail |
| Filter bots before processing | The results include both person and bot accounts. Filter to type === "person" in a Function node before sending emails or building a people picker. Bot accounts do not have email addresses. |
| Guest user email may be null | Guest users (invited without full workspace membership) may not return an email address. Use null-safe access and handle missing emails before routing notifications. |
| Cache for long workflows | If a workflow references many Notion users, call user/getMany once at the start and build a lookup map (id → email). Avoid calling user/get per-user in a loop, which multiplies API calls by the number of assignees. |
| Use ReturnAll for small workspaces | ReturnAll: true is efficient for workspaces under 100 users. For larger organizations, use cursor-based pagination to stay within rate limits. |
| Credentials in Credentials Manager | Always use {{ $credentials.notionApiToken }} — never hard-code the token. |
Workflow Examples
Example 1 — Build User Lookup Map for Bulk Notifications
Load all users once, build a map, then use it to resolve assignee IDs across many pages without additional API calls.
// Step 1: user/getMany (ReturnAll: true)
// Step 2: Function node — build lookup map
const userMap = {};
$output.getManyUsers.results
.filter(u => u.type === 'person')
.forEach(u => { userMap[u.id] = { name: u.name, email: u.email }; });
return { userMap };
// Step 3: database/query (all open tasks)
// Step 4: Loop over tasks
// Step 5 per task: lookup assignee from userMap (no extra API call)
const assignee = $vars.userMap[$json.properties.Assignee.people[0]?.id];
if (assignee?.email) {
// send email to assignee.email
}
Example 2 — HR System Sync Audit
Compare Notion workspace members to the active employee list from an HR system and flag discrepancies.
// Step 1: user/getMany (ReturnAll: true)
// Step 2: Function node — filter person users only
const notionEmails = results.filter(u => u.type === 'person').map(u => u.email).filter(Boolean);
// Step 3: HttpRequest — fetch active employee emails from HR API
// Step 4: Function node — find users in Notion but not in HR
const departed = notionEmails.filter(e => !hrEmails.includes(e));
// Step 5: Slack/postMessage — alert IT/security team
Example 3 — Name-to-UUID Resolution for Page Update
An external form captures a task assignee by name. Resolve to Notion UUID before updating the page property.
// Step 1: FormTrigger — { assigneeName: "Sarah Chen", pageId: "..." }
// Step 2: user/getMany (ReturnAll: true)
// Step 3: Function node
const user = $output.getManyUsers.results.find(u => u.name === $json.assigneeName);
if (!user) throw new Error("User not found: " + $json.assigneeName);
return { userId: user.id };
// Step 4: page/update
{
"Page": "{{ $json.pageId }}",
"Properties": {
"Assignee": { "people": [{ "object": "user", "id": "{{ $json.userId }}" }] }
}
}