Notes: Real-time & Sync
Section titled “Notes: Real-time & Sync”The Notes real-time API powers collaborative editing through WebSocket connections and mutation sync. Use these endpoints to provision a user identity, initialize and open WebSocket sessions, and batch-sync client-side mutations back to the server.
Identity
Section titled “Identity”GET /api/v1/notes/me
Section titled “GET /api/v1/notes/me”Returns the current user identity, including userId, username, role, and notebookId. The user and notebook are auto-provisioned on first call.
This endpoint takes no parameters.
{}curl -X GET https://api.hoody.com/api/v1/notes/me \ -H "Authorization: Bearer <token>"const identity = await client.notes.identity.get();WebSocket Sessions
Section titled “WebSocket Sessions”A WebSocket connection is established in two steps: first POST /api/v1/notes/sockets to initialize a session and receive a socketId, then GET /api/v1/notes/sockets/{socketId} to perform the HTTP-to-WebSocket upgrade.
POST /api/v1/notes/sockets
Section titled “POST /api/v1/notes/sockets”Creates a new socket session and returns the id used to open a WebSocket connection.
This endpoint takes no parameters.
{ "id": "sock_01HXYZMNOPQRST"}{ "message": "Invalid request", "code": "BAD_REQUEST", "details": [ { "path": "body", "message": "Request body could not be processed" } ]}{ "message": "Internal server error", "code": "INTERNAL_ERROR", "details": [ { "path": "server", "message": "Failed to create socket session" } ]}curl -X POST https://api.hoody.com/api/v1/notes/sockets \ -H "Authorization: Bearer <token>"const session = await client.notes.sockets.init();GET /api/v1/notes/sockets/{socketId}
Section titled “GET /api/v1/notes/sockets/{socketId}”Upgrades an HTTP connection to a WebSocket using a previously initialized socket id.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
socketId | path | string | Yes | socketId path parameter |
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
socketId | path | string | Yes | The socket session ID returned by POST /api/v1/notes/sockets |
{ "message": "Invalid socketId format", "code": "BAD_REQUEST", "details": [ { "path": "socketId", "message": "Must be a valid socket session identifier" } ]}{ "message": "Failed to upgrade connection", "code": "INTERNAL_ERROR", "details": [ { "path": "server", "message": "Unexpected error during WebSocket upgrade" } ]}curl -X GET https://api.hoody.com/api/v1/notes/sockets/sock_01HXYZMNOPQRST \ -H "Authorization: Bearer <token>" \ -H "Upgrade: websocket" \ -H "Connection: Upgrade"await client.notes.sockets.open({ socketId: "sock_01HXYZMNOPQRST" });Mutation Sync
Section titled “Mutation Sync”POST /api/v1/notes/notebooks/{notebookId}/mutations
Section titled “POST /api/v1/notes/notebooks/{notebookId}/mutations”Processes a batch of client-side mutations — node CRUD, reactions, interactions, and document updates. Up to 500 mutations may be sent per request.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
notebookId | path | string | Yes | The notebook identifier mutations are scoped to |
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
mutations | array | Yes | Array of mutation objects. Maximum 500 entries per request. |
Each entry in mutations shares a common envelope:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Client-generated mutation identifier |
createdAt | string | Yes | Client-side timestamp when the mutation was created (ISO 8601) |
type | string | Yes | Mutation type discriminator. One of node.create, node.update, node.delete, node.reaction.create, node.reaction.delete, node.interaction.seen, node.interaction.opened, document.update |
data | object | Yes | Mutation-type-specific payload (see below) |
The data object shape depends on type:
| Type | Required data fields |
|---|---|
node.create | nodeId, updateId, createdAt, data |
node.update | nodeId, updateId, data, createdAt |
node.delete | nodeId, rootId, deletedAt |
node.reaction.create | nodeId, reaction, rootId, createdAt |
node.reaction.delete | nodeId, reaction, rootId, deletedAt |
node.interaction.seen | nodeId, collaboratorId, seenAt |
node.interaction.opened | nodeId, collaboratorId, openedAt |
document.update | documentId, updateId, data, createdAt |
{ "mutations": [ { "id": "mut_01HXYZAAAAAAAA", "createdAt": "2024-01-15T12:34:56.000Z", "type": "node.create", "data": { "nodeId": "nod_01HXYZBULLET01", "updateId": "upd_01HXYZUPDATE01", "createdAt": "2024-01-15T12:34:55.000Z", "data": "eyJ0eXBlIjoicGFyYWdyYXBoIn0=" } }, { "id": "mut_01HXYZBBBBBBBB", "createdAt": "2024-01-15T12:34:57.000Z", "type": "node.reaction.create", "data": { "nodeId": "nod_01HXYZBULLET01", "reaction": "👍", "rootId": "nod_01HXYZROOT000", "createdAt": "2024-01-15T12:34:57.000Z" } }, { "id": "mut_01HXYZCCCCCCCC", "createdAt": "2024-01-15T12:34:58.000Z", "type": "document.update", "data": { "documentId": "doc_01HXYZDOCUMENT1", "updateId": "upd_01HXYZUPDATE02", "data": "eyJ0ZXh0IjoiVXBkYXRlZCBjb250ZW50In0=", "createdAt": "2024-01-15T12:34:58.000Z" } } ]}{}curl -X POST https://api.hoody.com/api/v1/notes/notebooks/ntb_01HXYZGHIJKLM/mutations \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "mutations": [ { "id": "mut_01HXYZAAAAAAAA", "createdAt": "2024-01-15T12:34:56.000Z", "type": "node.create", "data": { "nodeId": "nod_01HXYZBULLET01", "updateId": "upd_01HXYZUPDATE01", "createdAt": "2024-01-15T12:34:55.000Z", "data": "eyJ0eXBlIjoicGFyYWdyYXBoIn0=" } } ] }'const results = await client.notes.mutations.sync({ notebookId: "ntb_01HXYZGHIJKLM", data: { mutations: [ { id: "mut_01HXYZAAAAAAAA", createdAt: "2024-01-15T12:34:56.000Z", type: "node.create", data: { nodeId: "nod_01HXYZBULLET01", updateId: "upd_01HXYZUPDATE01", createdAt: "2024-01-15T12:34:55.000Z", data: "eyJ0eXBlIjoicGFyYWdyYXBoIn0=" } }, { id: "mut_01HXYZBBBBBBBB", createdAt: "2024-01-15T12:34:57.000Z", type: "node.reaction.create", data: { nodeId: "nod_01HXYZBULLET01", reaction: "👍", rootId: "nod_01HXYZROOT000", createdAt: "2024-01-15T12:34:57.000Z" } } ] }});