node:update
Update fields of an existing node via WebSocket event. Equivalent to PUT /api/node in REST.
Visibility & Permissions
- Caller must have editor access on the node being updated.
- ACL violations result in
forbiddenerror. - Updates are partial: only provided fields are modified.
Fields omitted in the payload remain unchanged.
Client → Server node:update
{
"id": "<uuid>", // required
"title": "New title",
"status": 3,
}
Success (ack)
{
"ok": true,
"diff": {
"batchId": "uuid",
"actor": {
"username": "alice",
"email": "alice@example.com"
},
"ts": "2025-09-25T10:00:00Z",
"nodes": [
{
"op": 1, // History operation NODE_UPDATE=1
"before": {
"id": "uuid",
"title": "Old title",
"version": 4
},
"after": {
"id": "uuid",
"title": "New title",
"version": 5,
"shareRoots": ["root-uuid-1", "root-uuid-2"],
"lastEditedTime": "2025-09-25T10:00:00Z"
}
},
{
"op": 2, // History operation NODE_STATUS=2; changing status is a special separate operation
"before": {
"id": "uuid",
"status": 1, // 1=Available
"version": 5
},
"after": {
"id": "uuid",
"title": "New title",
"status": 3, // 3=Completed
"version": 6,
"shareRoots": ["root-uuid-1", "root-uuid-2"],
"lastEditedTime": "2025-09-25T10:00:00Z"
}
},
{ // Side effect
"op": 2,
"before": {
"id": "uuid2",
"status": 2, // 2=Blocked
"version": 10
},
"after": {
"id": "uuid2",
"title": "New title",
"status": 1, // 1=Available
"version": 11,
"shareRoots": ["root-uuid-1", "root-uuid-2"],
"lastEditedTime": "2025-09-25T10:00:00Z"
}
}
],
"links": [],
"user": [],
"access": [],
}
}
info
Changing status is always a separate operation.
note
The diff includes only changed fields in before and after.
Consumers must merge by id+version, not overwrite blindly.
Side effects (e.g., blocking parent status updates) will also be included with their minimal changes.
Broadcasting (graph:diff)
On success the server also emits
graph:diffto all other clients in the ACL rooms.
The origin client receives the ACK directly and is excluded from the broadcast.
Error (ack)
{
"ok": false,
"error": "bad_request" | "forbidden" | "not_found" | "conflict" | "internal.exception",
"message": "<optional human-readable>",
"trace_id": "abc123def456"
}
Errors: see error codes
Examples
JavaScript
socket.emit("node:update", { id: "<uuid>", title: "Renamed Task" }, (resp) => {
if (resp.ok) {
console.log("Node updated", resp.diff);
} else {
console.error("Update failed", resp.error);
}
});
Python (socketio-client)
import socketio
sio = socketio.Client()
sio.connect("https://synaptask.space", headers={"Authorization": "Bearer <API_TOKEN>"})
resp = sio.call("node:update", {"id": "<uuid>", "status": 2}, timeout=5)
if resp.get("ok"):
print("Node updated:", resp["diff"])
else:
print("Failed:", resp["error"])
See also Node concept and History concept