# Notes: Collaboration

**Page:** api/notes/collaborators

[Download Raw Markdown](./api/notes/collaborators.md)

---

{/* AUTO-GENERATED — Do not edit manually. Regenerate with: npm run docs:api:generate */}



The Notes Collaboration API manages user access and engagement on notebook nodes. Use these endpoints to list and modify collaborators (with per-node roles), add and remove emoji reactions, and invite users to a notebook or change their notebook-wide role.


Collaborator roles on a node (`admin`, `editor`, `collaborator`, `viewer`) are distinct from a user's notebook-wide role (`owner`, `admin`, `collaborator`, `guest`, `none`). Use the node-scoped endpoints to control access to individual sections, pages, and databases.


## Collaborators

Manage per-node collaborators and their roles. Node-level collaborator management requires admin permission on the target node.

### `GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/collaborators`

Returns all collaborators on a node with their roles and user info.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `notebookId` | path | string | Yes | The notebook that contains the node |
| `nodeId` | path | string | Yes | The node whose collaborators should be listed |



```bash
curl -X GET "https://api.hoody.com/api/v1/notes/notebooks/nb_8f3a1c2b/nodes/node_4d2e9f1a/collaborators" \
  -H "Authorization: Bearer <token>"
```


```ts
const collaborators = await client.notes.collaborators.list({
  notebookId: "nb_8f3a1c2b",
  nodeId: "node_4d2e9f1a"
});
```


```json
{
  "collaborators": [
    {
      "userId": "user_3a8c1f0e",
      "role": "admin",
      "name": "Ada Lovelace",
      "username": "ada",
      "avatar": "https://cdn.hoody.com/avatars/ada.png",
      "createdAt": "2024-11-02T10:15:32.000Z",
      "updatedAt": "2024-12-01T14:08:11.000Z"
    },
    {
      "userId": "user_5b9d2a14",
      "role": "editor",
      "name": "Grace Hopper",
      "username": "grace",
      "avatar": null,
      "createdAt": "2024-11-04T09:22:01.000Z",
      "updatedAt": null
    }
  ]
}
```


```json
{
  "message": "You do not have access to this node.",
  "code": "forbidden",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Access denied | User does not have permission to access this node | Check collaborator list or request access from the node admin |


```json
{
  "message": "Node not found.",
  "code": "not_found",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Node not found | No node exists with the provided ID in this notebook | Verify node ID using listNodes or listNodeChildren |



### `POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/collaborators`

Adds a user as a collaborator on a node with a specified role. Requires admin permission.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `notebookId` | path | string | Yes | The notebook that contains the node |
| `nodeId` | path | string | Yes | The node to add the collaborator to |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `collaboratorId` | string | Yes | The user ID to add as a collaborator |
| `role` | string | Yes | The role to assign. One of: `admin`, `editor`, `collaborator`, `viewer` |



```bash
curl -X POST "https://api.hoody.com/api/v1/notes/notebooks/nb_8f3a1c2b/nodes/node_4d2e9f1a/collaborators" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "collaboratorId": "user_5b9d2a14",
    "role": "editor"
  }'
```


```ts
await client.notes.collaborators.add({
  notebookId: "nb_8f3a1c2b",
  nodeId: "node_4d2e9f1a",
  data: {
    collaboratorId: "user_5b9d2a14",
    role: "editor"
  }
});
```


```json
{
  "userId": "user_5b9d2a14",
  "role": "editor",
  "createdAt": "2024-12-05T11:42:17.000Z",
  "updatedAt": null
}
```


```json
{
  "message": "Node type does not support collaborators.",
  "code": "bad_request",
  "details": [
    {
      "path": "nodeId",
      "message": "This node type cannot have collaborators"
    }
  ]
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Unsupported node type | This node type does not support collaborators | Collaborators can only be added to sections, pages, and databases |


```json
{
  "message": "You do not have permission to manage collaborators.",
  "code": "forbidden",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Not an admin | Only admins can manage collaborators on this node | Request admin access from the node owner |


```json
{
  "message": "Collaborator user was not found.",
  "code": "user_not_found",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `user_not_found` | User not found | The collaborator user does not exist in this notebook | Verify user ID or create the user with createUsers first |


```json
{
  "message": "Idempotency key conflict.",
  "code": "bad_request",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Idempotency conflict | A different request was already made with the same idempotency key | Use a new idempotency key for a different request |


```json
{
  "message": "An unexpected error occurred.",
  "code": "unknown",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `unknown` | Internal server error | An unexpected error occurred while processing the request | Retry the request; if it persists, contact support |



### `PATCH /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/collaborators/{collaboratorId}`

Changes the role of an existing collaborator. Requires admin permission.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `notebookId` | path | string | Yes | The notebook that contains the node |
| `nodeId` | path | string | Yes | The node whose collaborator is being updated |
| `collaboratorId` | path | string | Yes | The collaborator user ID to update |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `role` | string | Yes | The new role to assign. One of: `admin`, `editor`, `collaborator`, `viewer` |



```bash
curl -X PATCH "https://api.hoody.com/api/v1/notes/notebooks/nb_8f3a1c2b/nodes/node_4d2e9f1a/collaborators/user_5b9d2a14" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "viewer"
  }'
```


```ts
await client.notes.collaborators.update({
  notebookId: "nb_8f3a1c2b",
  nodeId: "node_4d2e9f1a",
  collaboratorId: "user_5b9d2a14",
  data: {
    role: "viewer"
  }
});
```


```json
{
  "userId": "user_5b9d2a14",
  "role": "viewer",
  "createdAt": "2024-11-04T09:22:01.000Z",
  "updatedAt": "2024-12-05T12:00:44.000Z"
}
```


```json
{
  "message": "Node type does not support collaborators.",
  "code": "bad_request",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Unsupported node type | This node type does not support collaborators | Collaborators can only be managed on sections, pages, and databases |


```json
{
  "message": "You do not have permission to manage collaborators.",
  "code": "forbidden",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Not an admin | Only admins can change collaborator roles | Request admin access from the node owner |


```json
{
  "message": "Collaborator not found.",
  "code": "not_found",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Collaborator not found | No collaborator with the given ID exists on this node | Verify collaborator ID using listCollaborators |


```json
{
  "message": "An unexpected error occurred.",
  "code": "unknown",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `unknown` | Internal server error | An unexpected error occurred while processing the request | Retry the request; if it persists, contact support |



### `DELETE /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/collaborators/{collaboratorId}`

Removes a collaborator from a node. Requires admin permission.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `notebookId` | path | string | Yes | The notebook that contains the node |
| `nodeId` | path | string | Yes | The node to remove the collaborator from |
| `collaboratorId` | path | string | Yes | The collaborator user ID to remove |



```bash
curl -X DELETE "https://api.hoody.com/api/v1/notes/notebooks/nb_8f3a1c2b/nodes/node_4d2e9f1a/collaborators/user_5b9d2a14" \
  -H "Authorization: Bearer <token>"
```


```ts
await client.notes.collaborators.remove({
  notebookId: "nb_8f3a1c2b",
  nodeId: "node_4d2e9f1a",
  collaboratorId: "user_5b9d2a14"
});
```


```json
{
  "success": true
}
```


```json
{
  "message": "Node type does not support collaborators.",
  "code": "bad_request",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Unsupported node type | This node type does not support collaborators | Collaborators can only be managed on sections, pages, and databases |


```json
{
  "message": "You do not have permission to manage collaborators.",
  "code": "forbidden",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Not an admin | Only admins can remove collaborators | Request admin access from the node owner |


```json
{
  "message": "Collaborator not found.",
  "code": "not_found",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Collaborator not found | No collaborator with the given ID exists on this node | Verify collaborator ID using listCollaborators |


```json
{
  "message": "An unexpected error occurred.",
  "code": "unknown",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `unknown` | Internal server error | An unexpected error occurred while processing the request | Retry the request; if it persists, contact support |



## Reactions

Add, list, and remove emoji reactions on nodes. Reactions are scoped to the current authenticated user.

### `GET /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/reactions`

Returns all reactions on a node with the collaborator who reacted.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `notebookId` | path | string | Yes | The notebook that contains the node |
| `nodeId` | path | string | Yes | The node whose reactions should be listed |



```bash
curl -X GET "https://api.hoody.com/api/v1/notes/notebooks/nb_8f3a1c2b/nodes/node_4d2e9f1a/reactions" \
  -H "Authorization: Bearer <token>"
```


```ts
const reactions = await client.notes.reactions.list({
  notebookId: "nb_8f3a1c2b",
  nodeId: "node_4d2e9f1a"
});
```


```json
{
  "reactions": [
    {
      "reaction": "🎉",
      "collaboratorId": "user_3a8c1f0e",
      "createdAt": "2024-12-05T10:00:12.000Z",
      "name": "Ada Lovelace",
      "username": "ada"
    },
    {
      "reaction": "🚀",
      "collaboratorId": "user_5b9d2a14",
      "createdAt": "2024-12-05T10:05:33.000Z",
      "name": "Grace Hopper",
      "username": "grace"
    }
  ]
}
```


```json
{
  "message": "You do not have access to this node.",
  "code": "forbidden",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Access denied | User does not have permission to access this node | Check collaborator list or request access from the node admin |


```json
{
  "message": "Node not found.",
  "code": "not_found",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Node not found | No node exists with the provided ID in this notebook | Verify node ID using listNodes or listNodeChildren |



### `POST /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/reactions`

Adds an emoji reaction to a node on behalf of the current user.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `notebookId` | path | string | Yes | The notebook that contains the node |
| `nodeId` | path | string | Yes | The node to react to |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `reaction` | string | Yes | The reaction to add (1–64 characters). Typically an emoji. |



```bash
curl -X POST "https://api.hoody.com/api/v1/notes/notebooks/nb_8f3a1c2b/nodes/node_4d2e9f1a/reactions" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "reaction": "🎉"
  }'
```


```ts
await client.notes.reactions.add({
  notebookId: "nb_8f3a1c2b",
  nodeId: "node_4d2e9f1a",
  data: {
    reaction: "🎉"
  }
});
```


```json
{
  "reaction": "🎉",
  "collaboratorId": "user_3a8c1f0e",
  "createdAt": "2024-12-05T10:00:12.000Z"
}
```


```json
{
  "message": "Invalid request payload.",
  "code": "bad_request",
  "details": [
    {
      "path": "reaction",
      "message": "reaction must be between 1 and 64 characters"
    }
  ]
}
```


```json
{
  "message": "You do not have access to this node.",
  "code": "forbidden",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Access denied | User does not have permission to access this node | Check collaborator list or request access from the node admin |


```json
{
  "message": "Node not found.",
  "code": "not_found",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Node not found | No node exists with the provided ID in this notebook | Verify node ID using listNodes or listNodeChildren |


```json
{
  "message": "Idempotency key conflict.",
  "code": "bad_request",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Idempotency conflict | A different request was already made with the same idempotency key | Use a new idempotency key for a different request |


```json
{
  "message": "An unexpected error occurred.",
  "code": "unknown",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `unknown` | Internal server error | An unexpected error occurred while processing the request | Retry the request; if it persists, contact support |



### `DELETE /api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/reactions/{reaction}`

Removes an emoji reaction from a node for the current user.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `notebookId` | path | string | Yes | The notebook that contains the node |
| `nodeId` | path | string | Yes | The node from which to remove the reaction |
| `reaction` | path | string | Yes | The exact reaction string to remove (e.g. `🎉`) |



```bash
curl -X DELETE "https://api.hoody.com/api/v1/notes/notebooks/nb_8f3a1c2b/nodes/node_4d2e9f1a/reactions/%F0%9F%8E%89" \
  -H "Authorization: Bearer <token>"
```


```ts
await client.notes.reactions.remove({
  notebookId: "nb_8f3a1c2b",
  nodeId: "node_4d2e9f1a",
  reaction: "🎉"
});
```


```json
{
  "success": true
}
```


```json
{
  "message": "You do not have access to this node.",
  "code": "forbidden",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Access denied | User does not have permission to access this node | Check collaborator list or request access from the node admin |


```json
{
  "message": "Node not found.",
  "code": "not_found",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Node not found | No node exists with the provided ID in this notebook | Verify node ID using listNodes or listNodeChildren |


```json
{
  "message": "An unexpected error occurred.",
  "code": "unknown",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `unknown` | Internal server error | An unexpected error occurred while processing the request | Retry the request; if it persists, contact support |



## Notebook Users

Manage users that belong to a notebook and their notebook-wide role. These endpoints require owner or admin permission on the notebook.

### `POST /api/v1/notes/notebooks/{notebookId}/users`

Creates one or more users in the notebook by username. Returns created users and any errors.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `notebookId` | path | string | Yes | The notebook to invite users to |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `users` | array | Yes | List of users to invite (max 50). Each item requires `username` and `role`. |
| `users[].username` | string | Yes | The username of the user to invite |
| `users[].role` | string | Yes | The notebook role to assign. One of: `owner`, `admin`, `collaborator`, `guest`, `none` |



```bash
curl -X POST "https://api.hoody.com/api/v1/notes/notebooks/nb_8f3a1c2b/users" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "users": [
      { "username": "grace", "role": "editor" },
      { "username": "linus", "role": "collaborator" }
    ]
  }'
```


```ts
await client.notes.users.invite({
  notebookId: "nb_8f3a1c2b",
  data: {
    users: [
      { username: "grace", role: "editor" },
      { username: "linus", role: "collaborator" }
    ]
  }
});
```


```json
{
  "users": [
    {
      "id": "user_5b9d2a14",
      "name": "Grace Hopper",
      "avatar": "https://cdn.hoody.com/avatars/grace.png",
      "role": "editor",
      "customName": null,
      "customAvatar": null,
      "createdAt": "2024-12-05T10:15:32.000Z",
      "updatedAt": null,
      "revision": "rev_1a2b3c4d",
      "status": 1
    }
  ],
  "errors": [
    {
      "username": "linus",
      "error": "Username already exists in notebook"
    }
  ]
}
```


```json
{
  "message": "At least one user is required.",
  "code": "user_input_required",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `user_input_required` | User input required | At least one user must be provided in the request body | Provide a non-empty users array with username and role |


```json
{
  "message": "You do not have permission to add users.",
  "code": "user_invite_no_access",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `notebook_readonly` | Notebook is read-only | The notebook is in read-only mode and cannot be modified | Contact the notebook owner to restore write access |
| `user_invite_no_access` | No permission to add users | User role does not have permission to add users to this notebook | Only owners and admins can add users |


```json
{
  "message": "Notebook not found.",
  "code": "not_found",
  "details": []
}
```



### `PATCH /api/v1/notes/notebooks/{notebookId}/users/{userId}/role`

Changes the notebook role of a user. Requires owner or admin permission.

#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `notebookId` | path | string | Yes | The notebook that contains the user |
| `userId` | path | string | Yes | The user whose role should be changed |

#### Request Body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `role` | string | Yes | The new notebook role. One of: `owner`, `admin`, `collaborator`, `guest`, `none` |



```bash
curl -X PATCH "https://api.hoody.com/api/v1/notes/notebooks/nb_8f3a1c2b/users/user_5b9d2a14/role" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "admin"
  }'
```


```ts
await client.notes.users.updateRole({
  notebookId: "nb_8f3a1c2b",
  userId: "user_5b9d2a14",
  data: {
    role: "admin"
  }
});
```


```json
{
  "id": "user_5b9d2a14",
  "name": "Grace Hopper",
  "avatar": "https://cdn.hoody.com/avatars/grace.png",
  "role": "admin",
  "customName": null,
  "customAvatar": null,
  "createdAt": "2024-12-05T10:15:32.000Z",
  "updatedAt": "2024-12-05T12:30:11.000Z",
  "revision": "rev_9z8y7x6w",
  "status": 1
}
```


```json
{
  "message": "Invalid role value.",
  "code": "bad_request",
  "details": [
    {
      "path": "role",
      "message": "role must be one of: owner, admin, collaborator, guest, none"
    }
  ]
}
```


```json
{
  "message": "You do not have permission to update user roles.",
  "code": "user_update_no_access",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `notebook_readonly` | Notebook is read-only | The notebook is in read-only mode and cannot be modified | Contact the notebook owner to restore write access |
| `user_update_no_access` | No permission to update users | User role does not have permission to change user roles | Only owners and admins can change user roles |


```json
{
  "message": "User not found.",
  "code": "user_not_found",
  "details": []
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `user_not_found` | User not found | No user exists with the provided ID in this notebook | Verify user ID using the users list |