Skip to content

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.

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.

{}

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.

Creates a new socket session and returns the id used to open a WebSocket connection.

This endpoint takes no parameters.

{
"id": "sock_01HXYZMNOPQRST"
}

Upgrades an HTTP connection to a WebSocket using a previously initialized socket id.

NameInTypeRequiredDescription
socketIdpathstringYessocketId path parameter
NameInTypeRequiredDescription
socketIdpathstringYesThe 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"
}
]
}

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.

NameInTypeRequiredDescription
notebookIdpathstringYesThe notebook identifier mutations are scoped to
FieldTypeRequiredDescription
mutationsarrayYesArray of mutation objects. Maximum 500 entries per request.

Each entry in mutations shares a common envelope:

FieldTypeRequiredDescription
idstringYesClient-generated mutation identifier
createdAtstringYesClient-side timestamp when the mutation was created (ISO 8601)
typestringYesMutation type discriminator. One of node.create, node.update, node.delete, node.reaction.create, node.reaction.delete, node.interaction.seen, node.interaction.opened, document.update
dataobjectYesMutation-type-specific payload (see below)

The data object shape depends on type:

TypeRequired data fields
node.createnodeId, updateId, createdAt, data
node.updatenodeId, updateId, data, createdAt
node.deletenodeId, rootId, deletedAt
node.reaction.createnodeId, reaction, rootId, createdAt
node.reaction.deletenodeId, reaction, rootId, deletedAt
node.interaction.seennodeId, collaboratorId, seenAt
node.interaction.openednodeId, collaboratorId, openedAt
document.updatedocumentId, 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"
}
}
]
}