<!--
hoody-notes Subskill (http)
Auto-generated by Hoody Skills Generator
Generated: 2026-05-06T18:38:24.304Z
Model: mimo-v2.5-pro + fixer:mimo-v2.5-pro
Mode: http


Tokens: 20631

DO NOT EDIT MANUALLY - Changes will be overwritten on next generation
-->

# hoody-notes Subskill

## Overview

### What is hoody-notes?

hoody-notes is a collaborative document and knowledge management service within the Hoody Kit ecosystem. It provides a structured, hierarchical content system organized around **notebooks**, **nodes**, and **documents** — enabling teams to create, organize, share, and collaborate on rich content in real time.

### Core Concepts

| Concept | Description |
|---------|-------------|
| **Notebook** | Top-level container for a collection of related content. Each notebook has members with roles (owner, admin, editor, viewer). |
| **Node** | A content item within a notebook. Types include: `section`, `page`, `channel`, `message`, `database`, `record`. Nodes form a tree hierarchy via `parentId`. Note: `message` nodes are typically child items within `channel` nodes, similar to how `record` nodes belong to `database` nodes. |
| **Document** | The rich-text content attached to a node. Composed of structured blocks (paragraphs, headings, lists, drawings, etc.). |
| **Database** | A node of type `database` that contains structured records with custom fields. |
| **Record** | A node of type `record` within a database, holding field values. |
| **Collaborator** | A user granted access to a specific node with a defined role. |
| **File** | Binary attachments uploaded to a notebook via the TUS resumable upload protocol. |
| **Version** | A snapshot of a document's content at a point in time, enabling history and restore. |

### When to Use hoody-notes

- **Knowledge bases**: Create structured documentation, wikis, or internal knowledge repositories.
- **Project management**: Organize tasks, notes, and resources within project notebooks.
- **Collaborative editing**: Multiple users editing documents with comments, reactions, and real-time sync.
- **Structured data**: Store and query structured records using database nodes.
- **Content publishing**: Export documents to static HTML for public delivery.
- **File management**: Upload and manage file attachments within notebooks.

### How It Fits Into Hoody Philosophy

hoody-notes follows Hoody's principles of:

- **Zero configuration**: Notebooks and users are auto-provisioned on first access via `GET /api/v1/notes/me`.
- **Isolation**: Each notebook is a self-contained workspace with its own access control.
- **Real-time collaboration**: WebSocket support via the sockets endpoint enables live updates.
- **Resumable uploads**: TUS protocol support ensures reliable file uploads even on unstable connections.
- **Batch operations**: The mutations endpoint allows efficient bulk operations from clients.
- **Version safety**: Document versioning provides undo capability and audit trails.

### Service Access

All requests are routed through Hoody Proxy using the container service URL pattern:

```
https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu
```

Authentication is handled automatically by Hoody Proxy. No API keys are needed in request headers — the proxy injects identity based on the authenticated session.

---

## Common Workflows

### 1. Health Check and Identity

#### Check Service Health

Verify the notes service is running and responsive.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/health"
```

Response:

```
{
  "status": "ok",
  "service": "notes",
  "version": "1.0.0",
  "buildTimestamp": "2025-01-15T10:30:00Z",
  "startTimestamp": "2025-01-20T08:00:00Z",
  "uptime": 86400,
  "memory": {
    "rss": 52428800,
    "heapUsed": 31457280,
    "heapTotal": 41943040
  },
  "fds": 24,
  "pid": 1234
}
```

#### Get Current User Identity

Retrieve the authenticated user's identity. This endpoint auto-provisions the user and their default notebook on first call.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/me"
```

Response:

```
{
  "userId": "usr_abc123def456",
  "username": "alice",
  "role": "owner",
  "notebookId": "nb_789xyz012"
}
```

**Important**: Save the `notebookId` from this response — it is needed for most subsequent operations.

---

### 2. Notebook Management

#### List All Notebooks

Retrieve all notebooks the current user is a member of.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks"
```

Response:

```
[
  {
    "notebookId": "nb_789xyz012",
    "name": "My Workspace",
    "description": "Personal notes and projects",
    "avatar": "avt_001",
    "status": "active",
    "role": "owner"
  }
]
```

#### Create a New Notebook

Create a notebook with a name. Description and avatar are optional.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Project Alpha"
  }'
```

Response:

```
{
  "notebookId": "nb_new123abc",
  "name": "Project Alpha",
  "description": "",
  "avatar": null,
  "status": "active",
  "role": "owner"
}
```

#### Get Notebook Details

Retrieve metadata for a specific notebook.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_new123abc"
```

#### Update a Notebook

Update notebook name, description, or avatar. Only owners can update.

```
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_new123abc" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Project Alpha - Updated"
  }'
```

#### Delete a Notebook

Permanently delete a notebook and all its data. Only owners can delete.

```
curl -s -X DELETE \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_new123abc"
```

---

### 3. Node Operations

#### List Nodes in a Notebook

Retrieve a paginated list of nodes. Filter by type, parentId, or rootId.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes?type=page&limit=20"
```

Response:

```
{
  "items": [
    {
      "nodeId": "node_abc111",
      "type": "page",
      "parentId": "node_root",
      "attributes": {
        "name": "Getting Started",
        "description": "Introduction to the project"
      },
      "createdAt": "2025-01-20T10:00:00Z",
      "updatedAt": "2025-01-20T14:30:00Z"
    }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}
```

#### Create a Node

Create a new node within a notebook. The `type` and `attributes` fields are required.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "page",
    "attributes": {
      "name": "Architecture Overview",
      "description": "System architecture documentation"
    }
  }'
```

Response:

```
{
  "nodeId": "node_def222",
  "type": "page",
  "parentId": null,
  "attributes": {
    "name": "Architecture Overview",
    "description": "System architecture documentation"
  },
  "createdAt": "2025-01-21T09:00:00Z",
  "updatedAt": "2025-01-21T09:00:00Z"
}
```

#### Create a Section with Children

Create a section node, then create child pages under it.

```
# Step 1: Create the section
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "section",
    "attributes": {
      "name": "Engineering"
    }
  }'
```

```
# Step 2: Create a child page (use parentId from step 1)
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "page",
    "attributes": {
      "name": "API Design",
      "parentId": "node_sec333"
    }
  }'
```

#### Get Node by ID

Retrieve full details of a single node.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_def222"
```

#### Get Node by Alias

Resolve a page node by its safe alias within the notebook. Aliases are generated by converting the node name to lowercase, replacing spaces with hyphens, and removing special characters. For example, 'Architecture Overview' becomes 'architecture-overview'.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/alias/architecture-overview"
```

#### List Node Children

Retrieve direct children of a node.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_sec333/children"
```

#### Update a Node

Update node attributes. The `attributes` field is required. Note: `type` and `parentId` cannot be changed.

```
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_def222" \
  -H "Content-Type: application/json" \
  -d '{
    "attributes": {
      "name": "Architecture Overview v2",
      "description": "Updated system architecture"
    }
  }'
```

#### Delete a Node

Permanently delete a node and all associated data (documents, files, reactions).

```
curl -s -X DELETE \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_def222"
```

---

### 4. Document Management

#### Get Document Content

Retrieve the document content for a node. Supports block filtering and line range queries.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/document"
```

Response:

```
{
  "nodeId": "node_abc111",
  "content": {
    "blocks": [
      {
        "id": "blk_001",
        "type": "paragraph",
        "text": "Welcome to the project documentation."
      },
      {
        "id": "blk_002",
        "type": "heading",
        "level": 2,
        "text": "Getting Started"
      }
    ]
  }
}
```

#### Create or Replace a Document

Use PUT to create a new document or fully replace an existing one. The `content` field is required.

```
curl -s -X PUT \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/document" \
  -H "Content-Type: application/json" \
  -d '{
    "content": {
      "blocks": [
        {
          "id": "blk_new001",
          "type": "paragraph",
          "text": "This is the complete document content."
        },
        {
          "id": "blk_new002",
          "type": "heading",
          "level": 1,
          "text": "Introduction"
        },
        {
          "id": "blk_new003",
          "type": "paragraph",
          "text": "This document covers the project overview."
        }
      ]
    }
  }'
```

#### Merge Content into a Document

Use PATCH to merge content into an existing document. Existing blocks are preserved unless overwritten by matching ID.

```
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/document" \
  -H "Content-Type: application/json" \
  -d '{
    "content": {
      "blocks": [
        {
          "id": "blk_new004",
          "type": "paragraph",
          "text": "This block is appended to the existing document."
        }
      ]
    }
  }'
```

#### Create an Export Ticket

Generate a short-lived export ticket for static HTML document delivery.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/export-ticket" \
  -H "Content-Type: application/json" \
  -d '{}'
```

Response:

```
{
  "ticket": "tkt_export_abc123xyz",
  "expiresAt": "2025-01-21T10:00:00Z"
}
```

#### Render a Drawing Block as SVG

Retrieve a drawing block rendered as an SVG image.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/blocks/blk_drawing001/svg?scale=2"
```

---

### 5. File Management (TUS Protocol)

File uploads use the TUS resumable upload protocol. The workflow involves creating an upload, uploading chunks, and optionally checking or aborting.

#### Step 1: Create Upload

Initialize a resumable upload session.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/files/file_001/tus" \
  -H "Content-Length: 0" \
  -H "Tus-Resumable: 1.0.0" \
  -H "Upload-Length: 1048576" \
  -H "Upload-Metadata: filename dGVzdC5wZGY="
```

#### Step 2: Upload Chunk

Upload file data in one or more chunks.

```
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/files/file_001/tus" \
  -H "Content-Type: application/offset+octet-stream" \
  -H "Tus-Resumable: 1.0.0" \
  -H "Upload-Offset: 0" \
  --data-binary @/path/to/file.pdf
```

#### Step 3: Check Upload Status

Check the current upload offset to resume interrupted uploads.

```
curl -s -X HEAD \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/files/file_001/tus" \
  -H "Tus-Resumable: 1.0.0"
```

#### Abort an Upload

Cancel an in-progress upload.

```
curl -s -X DELETE \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/files/file_001/tus" \
  -H "Tus-Resumable: 1.0.0"
```

#### List Files

Retrieve a paginated list of files in a notebook.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/files?limit=10"
```

Response:

```
{
  "items": [
    {
      "fileId": "file_001",
      "filename": "test.pdf",
      "contentType": "application/pdf",
      "size": 1048576,
      "createdAt": "2025-01-21T10:00:00Z"
    }
  ],
  "total": 1,
  "limit": 10,
  "offset": 0
}
```

#### Download a File

Download the binary content of an uploaded file.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/files/file_001" \
  -o downloaded-file.pdf
```

---

### 6. Collaborator Management

#### List Collaborators

Retrieve all collaborators on a node with their roles.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/collaborators"
```

Response:

```
[
  {
    "collaboratorId": "coll_001",
    "userId": "usr_abc123def456",
    "username": "alice",
    "role": "admin"
  }
]
```

#### Add a Collaborator

Add a user as a collaborator on a node. Requires admin permission. Both `collaboratorId` and `role` are required.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/collaborators" \
  -H "Content-Type: application/json" \
  -d '{
    "collaboratorId": "usr_bob789",
    "role": "editor"
  }'
```

#### Update Collaborator Role

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

```
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/collaborators/coll_002" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "viewer"
  }'
```

#### Remove a Collaborator

Remove a collaborator from a node. Requires admin permission.

```
curl -s -X DELETE \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/collaborators/coll_002"
```

---

### 7. Reactions

#### List Reactions

Retrieve all reactions on a node.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/reactions"
```

Response:

```
[
  {
    "reaction": "👍",
    "userId": "usr_abc123def456",
    "username": "alice"
  },
  {
    "reaction": "🎉",
    "userId": "usr_bob789",
    "username": "bob"
  }
]
```

#### Add a Reaction

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

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/reactions" \
  -H "Content-Type: application/json" \
  -d '{
    "reaction": "👍"
  }'
```

#### Remove a Reaction

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

```
curl -s -X DELETE \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/reactions/👍"
```

---

### 8. Interactions

#### Record "Seen" Interaction

Track that the current user has seen a node.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/interactions/seen" \
  -H "Content-Type: application/json" \
  -d '{}'
```

#### Record "Opened" Interaction

Track that the current user has opened a node.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/interactions/opened" \
  -H "Content-Type: application/json" \
  -d '{}'
```

---

### 9. Comments

#### List Comments

Retrieve all comments for a document node.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/comments"
```

Response:

```
[
  {
    "commentId": "cmt_001",
    "userId": "usr_abc123def456",
    "username": "alice",
    "content": "This section needs more detail.",
    "createdAt": "2025-01-21T10:00:00Z",
    "resolved": false
  }
]
```

#### Get Comment Anchors

Retrieve lightweight thread anchor metadata for comment decorations.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/comment-anchors"
```

#### Create a Comment

Add a new comment to a document node.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/comments" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Great work on this section!"
  }'
```

#### Edit a Comment

Update the content of an existing comment.

```
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/comments/cmt_001" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Updated: This section is well written."
  }'
```

#### Delete a Comment

Delete a comment and its replies.

```
curl -s -X DELETE \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/comments/cmt_001"
```

#### Reanchor a Comment

Update the root anchor for a comment thread.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/comments/cmt_001/reanchor" \
  -H "Content-Type: application/json" \
  -d '{
    "anchor": "blk_002"
  }'
```

#### Resolve a Comment

Mark a comment thread as resolved.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/comments/cmt_001/resolve" \
  -H "Content-Type: application/json" \
  -d '{}'
```

---

### 10. Versions

#### List Versions

Retrieve all versions for a document, ordered by revision descending.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/versions"
```

Response:

```
[
  {
    "versionId": "ver_003",
    "revision": 3,
    "createdAt": "2025-01-21T14:00:00Z",
    "createdBy": "usr_abc123def456"
  },
  {
    "versionId": "ver_002",
    "revision": 2,
    "createdAt": "2025-01-21T12:00:00Z",
    "createdBy": "usr_abc123def456"
  }
]
```

#### Create a Version

Capture the current document content as a new version snapshot.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/versions" \
  -H "Content-Type: application/json" \
  -d '{}'
```

#### Get a Specific Version

Retrieve a specific document version by ID.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/versions/ver_002"
```

#### Restore a Version

Restore a document to a previous version.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/versions/ver_002/restore" \
  -H "Content-Type: application/json" \
  -d '{}'
```

#### Delete a Version

Delete a specific document version.

```
curl -s -X DELETE \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/versions/ver_001"
```

---

### 11. Database Records

#### List Records

Retrieve a paginated list of records in a database. Supports JSON-encoded filters and sorts.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/databases/db_001/records?limit=20"
```

Response:

```
{
  "items": [
    {
      "recordId": "rec_001",
      "name": "Task: Fix login bug",
      "fields": {
        "status": "in-progress",
        "priority": "high",
        "assignee": "alice"
      }
    }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}
```

#### Create a Record

Create a new record in a database with a name and custom field values.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/databases/db_001/records" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Task: Implement search",
    "fields": {
      "status": "todo",
      "priority": "medium",
      "assignee": "bob"
    }
  }'
```

#### Search Records

Search records by name. Supports excluding specific record IDs.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/databases/db_001/records/search?q=login"
```

#### Get a Record

Retrieve a single record by ID.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/databases/db_001/records/rec_001"
```

#### Update a Record

Update a record name, avatar, or field values. Fields are merged with existing values.

```
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/databases/db_001/records/rec_001" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "status": "done"
    }
  }'
```

#### Delete a Record

Permanently delete a record from a database.

```
curl -s -X DELETE \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/databases/db_001/records/rec_001"
```

---

### 12. User Management

#### Create Users in a Notebook

Create one or more users by username.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/users" \
  -H "Content-Type: application/json" \
  -d '{
    "usernames": ["charlie", "diana"]
  }'
```

Response:

```
{
  "created": [
    {
      "userId": "usr_charlie001",
      "username": "charlie",
      "role": "viewer"
    },
    {
      "userId": "usr_diana002",
      "username": "diana",
      "role": "viewer"
    }
  ],
  "errors": []
}
```

#### Change User Role

Update a user's notebook role. Requires owner or admin permission.

```
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/users/usr_charlie001/role" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "editor"
  }'
```

---

### 13. Avatars

#### Upload an Avatar

Upload a raw image (JPEG, PNG, or WebP) as an avatar. The image is resized to 500x500 and converted to JPEG.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/avatars" \
  -H "Content-Type: image/png" \
  --data-binary @avatar.png
```

Response:

```
{
  "avatarId": "avt_new001"
}
```

#### Download an Avatar

Retrieve the avatar image as JPEG binary data.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/avatars/avt_new001" \
  -o avatar.jpg
```

---

### 14. WebSocket Connections

#### Initialize a Socket Session

Create a new socket session and receive a socket ID.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/sockets" \
  -H "Content-Type: application/json" \
  -d '{}'
```

Response:

```
{
  "socketId": "sock_abc123xyz"
}
```

#### Open WebSocket Connection

Upgrade an HTTP connection to WebSocket using the socket ID.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/sockets/sock_abc123xyz" \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=="
```

---

## Advanced Operations

### 1. Full Notebook Setup Workflow

This workflow demonstrates creating a complete notebook structure from scratch.

```
# Step 1: Get current user identity (auto-provisions if needed)
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/me"
```

```
# Step 2: Create a new notebook
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Engineering Wiki"
  }'
```

Response:

```
{
  "notebookId": "nb_new_wiki",
  "name": "Engineering Wiki",
  "description": "",
  "avatar": null,
  "status": "active",
  "role": "owner"
}
```

**Note**: In subsequent steps, replace `nb_new_wiki` with the actual `notebookId` from this response.

```
# Step 3: Create a root section
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_new_wiki/nodes" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "section",
    "attributes": {
      "name": "Documentation"
    }
  }'
```

```
# Step 4: Create a page under the section
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_new_wiki/nodes" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "page",
    "attributes": {
      "name": "Onboarding Guide",
      "parentId": "node_doc_section"
    }
  }'
```

```
# Step 5: Add content to the page
curl -s -X PUT \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_new_wiki/nodes/node_onboarding/document" \
  -H "Content-Type: application/json" \
  -d '{
    "content": {
      "blocks": [
        {
          "id": "blk_intro",
          "type": "heading",
          "level": 1,
          "text": "Welcome to Engineering"
        },
        {
          "id": "blk_body",
          "type": "paragraph",
          "text": "This guide will help you get started with our engineering practices."
        }
      ]
    }
  }'
```

```
# Step 6: Create a database for tracking tasks
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_new_wiki/nodes" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "database",
    "attributes": {
      "name": "Task Tracker"
    }
  }'
```

```
# Step 7: Add team members
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_new_wiki/users" \
  -H "Content-Type: application/json" \
  -d '{
    "usernames": ["bob", "charlie"]
  }'
```

```
# Step 8: Verify the structure
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_new_wiki/nodes"
```

---

### 2. Document Collaboration Workflow

Set up a collaborative document with comments and version tracking.

```
# Step 1: Create a page for collaboration
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "page",
    "attributes": {
      "name": "RFC: New Feature Design"
    }
  }'
```

```
# Step 2: Write initial document content
curl -s -X PUT \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_rfc/document" \
  -H "Content-Type: application/json" \
  -d '{
    "content": {
      "blocks": [
        {
          "id": "blk_title",
          "type": "heading",
          "level": 1,
          "text": "RFC: Search Feature"
        },
        {
          "id": "blk_summary",
          "type": "paragraph",
          "text": "This RFC proposes adding full-text search across all notebooks."
        },
        {
          "id": "blk_motivation",
          "type": "heading",
          "level": 2,
          "text": "Motivation"
        },
        {
          "id": "blk_motivation_body",
          "type": "paragraph",
          "text": "Users currently cannot search across notebooks, making it difficult to find information."
        }
      ]
    }
  }'
```

```
# Step 3: Create initial version snapshot
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_rfc/versions" \
  -H "Content-Type: application/json" \
  -d '{}'
```

```
# Step 4: Add collaborators
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_rfc/collaborators" \
  -H "Content-Type: application/json" \
  -d '{
    "collaboratorId": "usr_bob789",
    "role": "editor"
  }'
```

```
# Step 5: Collaborator adds a comment
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_rfc/comments" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Should we consider Elasticsearch for the backend?"
  }'
```

```
# Step 6: Update document based on feedback
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_rfc/document" \
  -H "Content-Type: application/json" \
  -d '{
    "content": {
      "blocks": [
        {
          "id": "blk_tech",
          "type": "heading",
          "level": 2,
          "text": "Technical Approach"
        },
        {
          "id": "blk_tech_body",
          "type": "paragraph",
          "text": "We will use Elasticsearch as the search backend for full-text indexing."
        }
      ]
    }
  }'
```

```
# Step 7: Create version after updates
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_rfc/versions" \
  -H "Content-Type: application/json" \
  -d '{}'
```

```
# Step 8: Resolve the comment
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_rfc/comments/cmt_001/resolve" \
  -H "Content-Type: application/json" \
  -d '{}'
```

---

### 3. Batch Mutations

Process multiple operations in a single request for efficiency.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/mutations" \
  -H "Content-Type: application/json" \
  -d '{
    "mutations": [
      {
        "type": "node.create",
        "payload": {
          "type": "page",
          "attributes": {
            "name": "Batch Page 1"
          }
        }
      },
      {
        "type": "node.create",
        "payload": {
          "type": "page",
          "attributes": {
            "name": "Batch Page 2"
          }
        }
      },
      {
        "type": "reaction.add",
        "payload": {
          "nodeId": "node_abc111",
          "reaction": "⭐"
        }
      }
    ]
  }'
```

Response:

```
{
  "results": [
    {
      "status": "success",
      "data": {
        "nodeId": "node_batch001"
      }
    },
    {
      "status": "success",
      "data": {
        "nodeId": "node_batch002"
      }
    },
    {
      "status": "success",
      "data": {
        "reaction": "⭐"
      }
    }
  ]
}
```

---

### 4. Error Recovery Patterns

#### Handling 404 — Resource Not Found

When a node or notebook is not found, verify the ID and your access permissions.

```
# Verify the notebook exists
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012"
```

```
{
  "error": "not_found",
  "message": "Notebook not found"
}
```

**Recovery**: List available notebooks to find the correct ID.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks"
```

#### Handling 403 — Forbidden

When permission is denied, check your role in the notebook.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012"
```

```
{
  "notebookId": "nb_789xyz012",
  "name": "Engineering Wiki",
  "role": "viewer"
}
```

**Recovery**: Request an admin to upgrade your role.

#### Handling 409 — Conflict

When a resource already exists or a version conflict occurs, retrieve the current state and merge.

```
# Get current document state
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/document"
```

#### Handling TUS Upload Interruptions

Resume an interrupted upload by checking the current offset.

```
# Check current upload progress
curl -s -X HEAD \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/files/file_001/tus" \
  -H "Tus-Resumable: 1.0.0"
```

```
# Resume from the returned offset
curl -s -X PATCH \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/files/file_001/tus" \
  -H "Content-Type: application/offset+octet-stream" \
  -H "Tus-Resumable: 1.0.0" \
  -H "Upload-Offset: 524288" \
  --data-binary @/path/to/file-remaining.pdf
```

---

### 5. Performance Considerations

#### Pagination

Use `limit` and `offset` parameters for large collections.

```
# First page
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes?limit=50&offset=0"

# Second page
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes?limit=50&offset=50"
```

#### Filtering Nodes

Filter by type to reduce payload size.

```
# Only pages
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes?type=page"

# Only children of a specific node
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes?parentId=node_sec333"
```

#### Batch Operations

Use the mutations endpoint to reduce HTTP round-trips.

```
curl -s -X POST \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/mutations" \
  -H "Content-Type: application/json" \
  -d '{
    "mutations": [
      {
        "type": "interaction.seen",
        "payload": {
          "nodeId": "node_001"
        }
      },
      {
        "type": "interaction.seen",
        "payload": {
          "nodeId": "node_002"
        }
      },
      {
        "type": "interaction.seen",
        "payload": {
          "nodeId": "node_003"
        }
      }
    ]
  }'
```

#### Document Block Filtering

Retrieve only specific blocks from a document.

```
curl -s -X GET \
  "https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu/api/v1/notes/notebooks/nb_789xyz012/nodes/node_abc111/document?blockIds=blk_001,blk_002"
```

---

## Quick Reference

### Most Common Endpoints

| Operation | Method | Path |
|-----------|--------|------|
| Health check | GET | `/api/v1/notes/health` |
| Get identity | GET | `/api/v1/notes/me` |
| List notebooks | GET | `/api/v1/notes/notebooks` |
| Create notebook | POST | `/api/v1/notes/notebooks` |
| List nodes | GET | `/api/v1/notes/notebooks/{notebookId}/nodes` |
| Create node | POST | `/api/v1/notes/notebooks/{notebookId}/nodes` |
| Get document | GET | `/api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document` |
| Update document | PUT | `/api/v1/notes/notebooks/{notebookId}/nodes/{nodeId}/document` |
| List records | GET | `/api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records` |
| Create record | POST | `/api/v1/notes/notebooks/{notebookId}/databases/{databaseId}/records` |
| Batch mutations | POST | `/api/v1/notes/notebooks/{notebookId}/mutations` |

### Essential Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `notebookId` | string | Notebook identifier (from `/me` or `/notebooks`) |
| `nodeId` | string | Node identifier |
| `databaseId` | string | Database node identifier |
| `recordId` | string | Record identifier |
| `fileId` | string | File identifier |
| `limit` | number | Pagination page size |
| `offset` | number | Pagination offset |
| `type` | string | Node type filter (`section`, `page`, `channel`, `message`, `database`, `record`) |
| `parentId` | string | Filter nodes by parent |
| `rootId` | string | Filter nodes by root ancestor |
| `alias` | string | Page safe alias for URL-friendly lookup |

### Required Request Fields

| Endpoint | Required Fields |
|----------|----------------|
| POST `/notebooks` | `name` (string) |
| PATCH `/notebooks/{notebookId}` | `name` (string) |
| POST `/notebooks/{notebookId}/nodes` | `type` (string), `attributes` (object) |
| PATCH `/notebooks/{notebookId}/nodes/{nodeId}` | `attributes` (object) |
| PUT `/nodes/{nodeId}/document` | `content` (object) |
| PATCH `/nodes/{nodeId}/document` | `content` (object) |
| POST `/nodes/{nodeId}/collaborators` | `collaboratorId` (string), `role` (string) |

### Node Types

| Type | Description |
|------|-------------|
| `section` | Container for organizing pages and other nodes |
| `page` | Document node with rich-text content |
| `channel` | Communication channel |
| `message` | Individual message |
| `database` | Structured data container |
| `record` | Entry within a database |

### Typical Response Formats

**Single resource:**

```
{
  "nodeId": "node_abc111",
  "type": "page",
  "attributes": {
    "name": "Example"
  }
}
```

**Paginated list:**

```
{
  "items": [],
  "total": 0,
  "limit": 20,
  "offset": 0
}
```

**Batch mutation result:**

```
{
  "results": [
    {
      "status": "success",
      "data": {}
    }
  ]
}
```

**Error:**

```
{
  "error": "not_found",
  "message": "Resource not found"
}
```

### Base URL Pattern

```
https://{projectId}-{containerId}-notes-{serviceId}.{node}.containers.hoody.icu
```

All paths are appended directly to this base URL. No additional `/api` prefix is needed beyond what is shown in the endpoint paths above.