πŸ”Œ API Reference

Read and write to your trees programmatically. Build integrations, automations, bots, and external tools on the same backend that powers the TreeOS apps.

πŸ”‘ Overview & Authentication
The TreeOS API lives at https://treeOS.ai/api/v1. All endpoints return JSON by default. Every write operation and most read operations require authentication.

API Keys are the recommended way to authenticate for programmatic access. Create and manage keys from your user profile page. Keys are sent as a request header:
x-api-key: YOUR_API_KEY
Key details:
β€’ Created and managed from your profile page
β€’ Each key can be individually revoked
β€’ Usage is tracked per key
β€’ Maximum of 10 active keys per user
β€’ Works with all endpoints (read and write)
πŸ‘‹ Identity (Me)
Use this endpoint to verify your API key and discover your userId. This is the first call most integrations make.
GET/api/v1/me
Returns your identity, plan, energy, and share token.
Response
{ "success": true, "userId": "abc-123", "username": "tabor", "profileType": "god", "planExpiresAt": "2026-12-31T...", "email": "you@email.com", "shareToken": "your-share-token", "storageUsageMb": 12.5, "energy": { "available": 87, "additional": 100, "total": 187 } }
Generate API keys from your profile page at /api/v1/user/:userId/api-keys?html. You can have up to 10 active keys and revoke them individually.
🌐 URL Modes: ?html & ?token
Every GET endpoint supports two query parameters that change how the response is delivered:
?token=YOUR_TOKEN
A URL access token that authenticates the request. Only required for GET routes when you don't have an API key header. Tokens are tied to your account and can be found or refreshed on your profile page.

Example: /api/v1/node/:nodeId/5/notes?token=abc123
?html
When present, the server returns a fully rendered HTML page instead of raw JSON. This is what the browser app uses. Without ?html, you always get JSON.

Example: /api/v1/node/:nodeId/5/notes?token=abc123&html
For API integrations, use the x-api-key header and omit both ?html and ?token. The token/html pattern is designed for shareable browser links.
🧠 Tree Chat
The highest-level endpoint for interacting with a tree. Send a message to any tree and get a natural language response back. It distills every other function (navigation, placement, notes, structure, queries) into a single call β€” send context in, build and read the tree, get a response out.

The AI walks the tree, finds where your idea belongs (or gathers context for a question), executes the operations, and returns a conversational answer. It works with whatever root you give it.
POST/api/v1/root/:rootId/chat
Send a message to a tree. The AI reads the tree, places ideas or answers questions, and returns a response.
Request Body
{ "message": "flights seem cheaper in late March" }
Response
{ "success": true, "answer": "Noted β€” added that to your flight planning." }
Works for both placing information and asking questions. The response is always natural language β€” no tree internals are exposed.
πŸ“Œ Tree Place
Place content onto a tree without generating a conversational response. The AI navigates the tree, finds where the idea belongs, and executes the operations β€” but skips the final response step, making it faster and cheaper than Tree Chat.

Returns structured results (what was placed and where) instead of natural language. Use Tree Chat above if you need a conversational reply.
POST/api/v1/root/:rootId/place
Place content onto a specific tree. The AI navigates, creates structure, and edits nodes β€” but does not generate a response.
Request Body
{ "message": "flights seem cheaper in late March" }
Response
{ "success": true, "stepSummaries": [...], "targetNodeId": "abc123", "targetPath": "Trip / Flights" }
Same orchestration as Tree Chat, minus the final response generation. Useful for bulk ingestion or automated pipelines where you don't need a conversational reply.
πŸ” Tree Query
Talk to your tree without it making any changes. The AI reads the tree and generates a response, but will never create, edit, or delete nodes. Useful for asking questions, getting summaries, or exploring what's in your tree without risk of modification.
POST/api/v1/root/:rootId/query
Query a tree in read-only mode. The AI reads the tree and responds but cannot make any edits.
Request Body
{ "message": "what are my top priorities right now?" }
Response
{ "success": true, "answer": "Based on your tree, your top priorities are..." }
Same orchestration as Tree Chat, but the classifier intent is forced to query-only. Even if the message sounds like a placement request, the AI will only respond with information and never edit the tree.
πŸ€– Raw Idea Chat
Same as Raw Idea Place, but synchronous β€” waits for the AI to finish and returns a conversational response along with which tree the idea was placed on. Useful when you want both placement and an answer in a single call.
POST/api/v1/user/:userId/raw-ideas/chat
Send text content directly. Creates the raw idea, places it on the best tree, and returns the AI's response -- all in one call.
Request Body
{ "content": "Your idea text here" }
Success Response
{ "success": true, "answer": "Your idea about X was placed under ...", "rootId": "abc123", "rootName": "My Tree", "targetNodeId": "def456", "targetNodePath": [ { "_id": "abc123", "name": "My Tree" }, { "_id": "xyz789", "name": "Health" }, { "_id": "def456", "name": "Sleep" } ], "rawIdeaId": "ghi789" }
Failure Response
{ "success": false, "error": "No trees available for this user" }
This is a long-running request (up to 19 minutes) -- the AI is doing real work behind the scenes.
POST/api/v1/user/:userId/raw-ideas/:rawIdeaId/chat
Same as above, but for an existing raw idea. Create a raw idea first via POST /api/v1/user/:userId/raw-ideas, then call this endpoint. Only works for pending text ideas.
Success Response
{ "success": true, "answer": "Your idea about X was placed under ...", "rootId": "abc123", "rootName": "My Tree", "targetNodeId": "def456", "targetNodePath": [ { "_id": "abc123", "name": "My Tree" }, { "_id": "xyz789", "name": "Health" }, { "_id": "def456", "name": "Sleep" } ] }
Failure Response
{ "success": false, "error": "No trees available for this user" }
This is a long-running request (up to 19 minutes) -- the AI is doing real work behind the scenes.
πŸ“₯ Raw Idea Place
Takes a raw idea created from a user's profile and places it onto a tree. The AI picks the best tree, finds the right place in it, and stores the idea β€” all automatically. No root ID needed.

This is fire-and-forget: it returns immediately while placement runs in the background. Does not generate a response β€” just places the idea. Use Raw Idea Chat above if you need a conversational reply.
POST/api/v1/user/:userId/raw-ideas/place
Send text content directly. Creates the raw idea and triggers AI placement in the background -- all in one call. Fire-and-forget.
Request Body
{ "content": "Your idea text here" }
Response
{ "message": "Orchestration started", "rawIdeaId": "abc123" } // 202 Accepted
Poll the idea's status via GET /api/v1/user/:userId/raw-ideas/:rawIdeaId to track progress. Use Raw Idea Chat above if you need a conversational reply.
POST/api/v1/user/:userId/raw-ideas/:rawIdeaId/place
Same as above, but for an existing raw idea. Create a raw idea first via POST /api/v1/user/:userId/raw-ideas, then trigger orchestration. Only works for pending text ideas.
Response
{ "message": "Orchestration started" } // 202 Accepted
πŸ”¬ Understand Tree
Runs AI-powered compression across an entire tree. The AI reads every node, summarizes leaf content, then merges summaries layer by layer until a single root encoding remains β€” a holistic understanding of the whole tree from a given perspective.

Example perspectives:
  • translate to Chinese
  • summarize this into 30 words
  • find all the places where marketing strategy is mentioned
  • extract every action item and deadline
  • identify contradictions or conflicting ideas
POST/api/v1/root/:rootId/understandings
Create a new understanding run. Pass a perspective in the request body to tell the AI what lens to use. Set incremental totrue to reuse an existing completed run and only reprocess nodes that changed since the last run.
Request Body
{ "perspective": "summarize this into 30 words", "incremental": true }
When incremental is true, the system finds the most recent completed run for the same root and perspective, detects which nodes have new contributions, and only reprocesses dirty nodes and their ancestors. If no prior run exists, a fresh run is created. Defaults to false.
POST/api/v1/root/:rootId/understandings/run/:runId/orchestrate
Run the AI understanding orchestrator on an existing run. The AI compresses all nodes layer by layer until a single root encoding remains. Only one orchestration can run at a time per run.
Success Response
{ "success": true, "understandingRunId": "abc123", "perspective": "summarize this into 30 words", "nodeCount": 12, "nodesProcessed": 11, "rootEncoding": "Compressed summary of the tree…" }
Already Complete
{ "success": true, "alreadyComplete": true, "rootEncoding": "…" }
Create a run first via POST /api/v1/root/:rootId/understandings, then trigger orchestration. This is a long-running request β€” the AI processes every node in the tree. Idempotent β€” if the run was interrupted, calling again picks up where it left off. If already complete, returns the final result immediately.
POST/api/v1/root/:rootId/understandings/run/:runId/stop
Stop an active understanding orchestration. Aborts the in-flight session and halts processing. Progress is preserved -- calling orchestrate again will resume from where it stopped.
Success Response
{ "success": true }
No Active Session
{ "success": false, "error": "No active session found for this run" }
πŸ‘€ User Endpoints
Profile, roots, API keys, contributions, notes, tags, raw ideas, invites, chat history, and custom LLM configuration.
Profile
GET/api/v1/user/:userId
Returns user profile, root nodes, and account metadata.
Create Root
POST/api/v1/user/:userId/createRoot
Create a new root tree for the user.
Request Body
{ "name": "My New Tree" }
API Keys
POST/api/v1/user/:userId/api-keys
Create a new API key.
Request Body
{ "name": "optional descriptive name" }
Response
{ "apiKey": "fcd8a7c7...", "message": "Store this key securely. You will not see it again." }
The full key is only shown once at creation time.
GET/api/v1/user/:userId/api-keys
List all API keys (active and revoked) for the user.
DELETE/api/v1/user/:userId/api-keys/:keyId
Revoke an API key. It will no longer authenticate requests.
Share Token
The URL token used for ?token= authentication on GET routes.
POST/api/v1/user/:userId/shareToken
Create or refresh the URL share token. Invalidates the previous token.
Contributions
GET/api/v1/user/:userId/contributions
All contributions made by the user across all trees.
Query Parameters
?limit=NUMBERMax results to return
?startDate=YYYY-MM-DDFilter from date
?endDate=YYYY-MM-DDFilter to date
Notes
GET/api/v1/user/:userId/notes
List or search all notes posted by the user.
Query Parameters
?q=SEARCHFull-text search query
?limit=NUMBERMax results to return
?startDate=YYYY-MM-DDFilter from date
?endDate=YYYY-MM-DDFilter to date
Tagged Notes (Inbox)
GET/api/v1/user/:userId/tags
Notes where the user has been @tagged by another user.
Raw Ideas
Unstructured inputs (text or files) that can later be converted into notes and placed into a tree.
POST/api/v1/user/:userId/raw-ideas
Create a new raw idea. Accepts multipart form data.
Form Fields
content: "text string" file: (optional file upload)
GET/api/v1/user/:userId/raw-ideas
List or search raw ideas. Defaults to pending ideas.
Query Parameters
?status=VALUEFilter by status. One of: pending (default), processing, succeeded, stuck, deferred, deleted, all
?q=SEARCHFull-text search query (searches within content)
?limit=NUMBERMax results to return (max 200, default 200)
?startDate=YYYY-MM-DDFilter from date
?endDate=YYYY-MM-DDFilter to date
Succeeded ideas are sorted by placement date (placedAt) descending. All others sort by creation date.
GET/api/v1/user/:userId/raw-ideas/:rawIdeaId
View a single raw idea including its status and AI session link.
POST/api/v1/user/:userId/raw-ideas/:rawIdeaId/transfer
Manually convert a raw idea into a note on a target node.
Request Body
{ "nodeId": "targetNodeId" }
Returns 409 if the idea is currently being processed by AI.
DELETE/api/v1/user/:userId/raw-ideas/:rawIdeaId
Permanently delete a raw idea.
Returns 409 if the idea has status processing or succeeded.
POST/api/v1/user/:userId/raw-ideas/auto-place
Toggle automatic raw idea placement. When enabled, pending ideas are placed every 15 minutes while you are offline.
Request Body
{ "enabled": true }
Response
{ "success": true, "enabled": true }
Requires Standard, Premium, or God plan. Returns 403 for Basic tier users.
Deleted Branches
Deleted branches are soft-deleted and can be restored.
GET/api/v1/user/:userId/deleted
List all soft-deleted branches for the user.
POST/api/v1/user/:userId/deleted/:nodeId/revive
Restore a deleted branch under a parent node.
Request Body
{ "targetParentId": "nodeId" }
POST/api/v1/user/:userId/deleted/:nodeId/reviveAsRoot
Restore a deleted branch as a new root tree.
Invites & Collaboration
GET/api/v1/user/:userId/invites
List pending invitations to collaborate on other users' trees.
POST/api/v1/user/:userId/invites/:inviteId
Accept or decline a collaboration invite.
Request Body
{ "accept": true } // true to accept, false to decline
Energy
GET/api/v1/user/:userId/energy
View current energy balance, plan tier, profile type, and custom LLM connection status.
Custom LLM Connections
Connect your own LLM providers for AI features. Each user can have up to 15 connections and assign them to different slots. Any OpenAI-compatible endpoint works.
GET/api/v1/user/:userId/custom-llm
List all custom LLM connections for the user.
Response
{ "success": true, "connections": [ { "_id": "...", "name": "GPT-4o", "baseUrl": "https://api.openai.com/v1", "model": "gpt-4o", ... } ] }
POST/api/v1/user/:userId/custom-llm
Create a new custom LLM connection.
Request Body
{ "name": "My GPT-4o", "baseUrl": "https://api.openai.com/v1", "apiKey": "sk-...", "model": "gpt-4o" }
Max 15 connections per user. API key is encrypted at rest.
PUT/api/v1/user/:userId/custom-llm/:connectionId
Update an existing connection's name, URL, key, or model.
Request Body
{ "name": "Updated Name", "baseUrl": "https://api.openai.com/v1", "apiKey": "sk-new-key", "model": "gpt-4o-mini" }
Only apiKey and name are optional β€” omit apiKey to keep the existing key.
DELETE/api/v1/user/:userId/custom-llm/:connectionId
Permanently delete a connection. Auto-removes it from all user slots and root tree assignments.
POST/api/v1/user/:userId/llm-assign
Assign a connection to a user-level LLM slot, or unassign by passing null.
Request Body
{ "slot": "main", "connectionId": "connection-id-here" }
Allowed Slots
main β€” Default slot used for tree chat/profile rawIdea β€” Used for raw idea auto-placement
Pass connectionId: null to unassign the slot.
AI Chats
GET/api/v1/user/:userId/chats
View AI chat history for a user, grouped by session.
Query Parameters
?limit=NUMBERMax sessions to return (default 10, max 10)
?sessionId=IDFilter to a specific session
?startDate=ISOFilter chats after this date
?endDate=ISOFilter chats before this date
Notifications
Notifications are generated automatically after tree dreams complete. Each dream produces a summary and a thought for the tree owner and contributors.
GET/api/v1/user/:userId/notifications
List notifications for the user, newest first.
Query Parameters
?rootId=IDFilter to a specific tree
?limit=NUMBERMax results (default 20, max 100)
?offset=NUMBERSkip N results for pagination
Response
{ "notifications": [ { "type": "dream-summary", "title": "...", "content": "...", "rootId": "...", "createdAt": "..." }, { "type": "dream-thought", "title": "...", "content": "...", "rootId": "...", "createdAt": "..." } ], "total": 12, "limit": 20, "offset": 0 }
Types: dream-summary (recap of what the dream did) and dream-thought (a reflective insight based on the dream activity).
🌳 Root Endpoints
Roots are the top-level entry point of a tree. Most tree-wide operations happen at this scope.
Tree Data
GET/api/v1/root/:rootId
Full tree including all children, metadata, notes, and contributions.
Query Parameters
?active=true|falseFilter by active status
?completed=true|falseFilter by completed status
?trimmed=true|falseFilter by trimmed status
Global Values
GET/api/v1/root/:rootId/values
All values aggregated across every child node in the tree.
Contributors & Ownership
POST/api/v1/root/:rootId/invite
Invite a collaborator to the tree.
Request Body
{ "userReceiving": "username-or-userId" }
POST/api/v1/root/:rootId/transfer-owner
Transfer tree ownership to another contributor.
Request Body
{ "userReceiving": "username-or-userId" }
POST/api/v1/root/:rootId/remove-user
Remove a contributor from the tree.
Request Body
{ "userReceiving": "username-or-userId" }
POST/api/v1/root/:rootId/retire
Archive the root (soft delete entire tree). Only the owner can do this when there are no other contributors.
Transaction Policy
POST/api/v1/root/:rootId/transaction-policy
Set the approval policy for transactions on this tree.
Request Body
{ "policy": "OWNER_ONLY" }
Allowed Values
OWNER_ONLY β€” Only the tree owner can approve ANYONE β€” Any contributor can approve MAJORITY β€” Majority of contributors must approve ALL β€” All contributors must approve
Tree AI Models
POST/api/v1/root/:rootId/llm-assign
Assign a custom LLM connection to a tree slot. Owner-only, requires paid plan.
Request Body
{ "slot": "placement", "connectionId": "connection-id-here" }
Allowed Slots
placement β€” Tree chat, navigation, node placement, classification understanding β€” Understanding runs (falls back to placement) respond β€” Final user-facing responses (falls back to placement) notes β€” Note creation and editing (falls back to placement) cleanup β€” Cleanup analysis and expansion (falls back to placement) drain β€” Short-term memory drain placement (falls back to placement) notification β€” Dream notification summary and thought (falls back to placement)
Pass connectionId: null to unassign and revert to the user's default. The connection must belong to the root owner. Unset slots fall back to placement, then to the user's default LLM.
Dream Time
POST/api/v1/root/:rootId/dream-time
Set or clear the nightly dream schedule for a tree. When set, the tree will automatically run cleanup and understanding processes at the specified time. Owner-only.
Request Body
{ "dreamTime": "03:00" }
Use 24-hour HH:MM format. Pass null or omit to disable dreaming.
AI Chats
GET/api/v1/root/:rootId/chats
View all AI chat sessions across the entire tree and its descendants.
Query Parameters
?limit=NUMBERMax sessions to return (default 10, max 10)
?sessionId=IDFilter to a specific session
?startDate=ISOFilter chats after this date
?endDate=ISOFilter chats before this date
Calendar
GET/api/v1/root/:rootId/calendar
All scheduled dates across every node in the tree.
Query Parameters
?month=0–11Filter by month (0 = Jan)
?year=YYYYFilter by year
?day=YYYY-MM-DDFilter by day (HTML mode)
πŸ“‘ Gateway Channels
Gateway channels connect your tree to external services like Telegram, Discord, and browser push notifications. Each root can have up to 10 channels. Channels have a direction (input, output, or input-output), a mode (place, query, or chat), and queue protection for input channels.
GET/api/v1/root/:rootId/gateway/channels
List all gateway channels for a root. Secrets are excluded from the response.
POST/api/v1/root/:rootId/gateway/channels
Create a new gateway channel.
Request Body (Telegram - Output)
{ "name": "My Telegram Bot", "type": "telegram", "direction": "output", "config": { "botToken": "123:ABC...", "chatId": "-100123..." }, "notificationTypes": ["dream-summary", "dream-thought"] }
Request Body (Telegram - Input/Output Chat)
{ "name": "Tree Chat Bot", "type": "telegram", "direction": "input-output", "mode": "read-write", "config": { "botToken": "123:ABC...", "chatId": "-100123..." }, "notificationTypes": ["dream-summary"], "queueBehavior": "respond" }
Request Body (Discord - Output)
{ "name": "Dream Updates", "type": "discord", "direction": "output", "config": { "webhookUrl": "https://discord.com/api/webhooks/..." }, "notificationTypes": ["dream-summary"] }
Request Body (Discord - Input/Output)
{ "name": "Discord Tree Chat", "type": "discord", "direction": "input-output", "mode": "read-write", "config": { "botToken": "discord-bot-token...", "discordChannelId": "1234567890123456789" }, "queueBehavior": "respond" }
Channel Types
telegram - Bot token + chat ID (input, output, or both) discord - Webhook URL (output) or bot token + channel ID (input) webapp - Browser push notification (output only)
Direction
output - Push notifications out (dream summaries, etc.) input - Receive messages in (place content, no response) input-output - Bidirectional (send messages, get responses)
Mode (for input channels)
write - Place mode: scans tree, makes edits, no response read - Query mode: reads tree, responds, no edits read-write - Chat mode: reads tree, makes edits, responds
Queue Behavior (for input channels)
respond - Replies "busy" when 2+ messages processing (default) silent - Drops overflow messages without responding
Notification Types (for output channels)
dream-summary - Nightly dream summary dream-thought - Nightly dream thought
All secrets (bot tokens, webhook URLs, push subscriptions) are encrypted at rest using AES-256-CBC. Maximum 10 channels per root. Discord input channels require Standard tier or above. Send "cancel" to any input channel to abort all active processing.
PUT/api/v1/root/:rootId/gateway/channels/:channelId
Update a channel's name, enabled status, notification types, queue behavior, or config.
Request Body
{ "enabled": false } { "queueBehavior": "silent" } { "notificationTypes": ["dream-summary"] }
DELETE/api/v1/root/:rootId/gateway/channels/:channelId
Delete a gateway channel. Only the channel creator can delete it. Automatically unregisters Telegram webhooks and disconnects Discord bots.
POST/api/v1/root/:rootId/gateway/channels/:channelId/test
Send a test notification through a channel to verify it works.
Response
{ "success": true }
πŸ“– Book & Sharing
The book view compiles all notes from a root and its children into a single hierarchical document. Books can be shared via public links.
GET/api/v1/root/:rootId/book
Book view β€” all notes from every child node compiled into a hierarchical format.
POST/api/v1/root/:rootId/book/generate
Generate a shareable link for the book. Returns a share ID for the public URL.
Response
{ "shareId": "abc123..." }
GET/api/v1/root/:rootId/book/share/:shareId
Public book link. Always renders HTML. No authentication required β€” anyone with the link can view.
This is the URL you share with others.
🧠 Understandings
Understandings are AI-powered analysis runs across a tree. Each run produces encodings for individual nodes, capturing the AI's interpretation of the node's state and content.

To run the full AI orchestrator, see Understand Tree above.
POST/api/v1/root/:rootId/understandings
Create a new understanding run for the tree. Pass incremental: true to reuse an existing completed run and only reprocess changed nodes.
Request Body
{ "perspective": "general", "incremental": true }
GET/api/v1/root/:rootId/understandings
List all understanding runs for this tree.
GET/api/v1/root/:rootId/understandings/:understandingNodeId
View a single understanding node and all of its run encodings across every run.
GET/api/v1/root/:rootId/understandings/run/:runId
View a specific understanding run and its results.
GET/api/v1/root/:rootId/understandings/run/:runId/:understandingNodeId
View a node's encoding state from the perspective of a specific understanding run.
POST/api/v1/root/:rootId/understandings/run/:runId/stop
Stop an active understanding orchestration. Progress is preserved and can be resumed.
πŸ”· Node Endpoints
Structure and hierarchy management. Nodes are the building blocks of every tree.
Node Management
GET/api/v1/node/:nodeId
Node metadata including all versions.
GET/api/v1/node/:nodeId/:version
A specific version with its values, goals, notes, and contributions.
POST/api/v1/node/:nodeId/:version/editName
Rename the node.
Request Body
{ "name": "New Node Name" }
POST/api/v1/node/:nodeId/createChild
Create a new child node under this node.
Request Body
{ "name": "Child Name" }
POST/api/v1/node/:nodeId/updateParent
Move this node under a different parent.
Request Body
{ "newParentId": "nodeId" }
POST/api/v1/node/:nodeId/delete
Soft delete this node and its entire branch. Can be restored from deleted branches.
βš™οΈ Scripts
Nodes can have attached scripts β€” small JavaScript programs that run in a sandboxed VM. Scripts can read and mutate node values, goals, status, schedule, and prestige.
POST/api/v1/node/:nodeId/script/create
Create or update a script on this node.
Request Body
{ "name": "dailyReset", "script": "setValueForNode('streak', 0);" }
Max 2000 characters. Scripts are node-scoped (not version-scoped).
GET/api/v1/node/:nodeId/script/:scriptId
View a script's source code and metadata.
POST/api/v1/node/:nodeId/script/:scriptId/execute
Execute a script on this node.
Response
{ "message": "Script executed successfully", "logs": ["console output line 1", "..."], "node": { "...updated node data" } }
Script environment: Sandboxed VM, 3-second timeout, up to 200 console.log lines captured.
Available Functions Inside Scripts
getApi() setValueForNode(key, value) setGoalForNode(key, goal) editStatusForNode(status) addPrestigeForNode() updateScheduleForNode(datetime | null)
Scripts run under the permissions of the calling user or API key. Failures are logged with captured output and error messages.
πŸ“‹ Node Version Endpoints
Version-scoped operations for status, schedule, prestige, notes, values, goals, and contributions.
Status & Schedule
POST/api/v1/node/:nodeId/:version/editStatus
Change status for this node. Optionally apply to all children.
Request Body
{ "status": "active | completed | trimmed", "isInherited": true }
isInherited (optional, default false) β€” when true, the status change cascades to all children.
POST/api/v1/node/:nodeId/:version/editSchedule
Set or clear the scheduled date for this node.
Request Body
{ "newSchedule": "2026-03-15T09:00:00Z", "reeffectTime": 24 } // clear schedule: { "newSchedule": null }
reeffectTime is optional β€” hours until the schedule repeats after prestige (recurring interval).
POST/api/v1/node/:nodeId/:version/prestige
Add a new version (prestige) to this node. Creates version N+1.
Notes
GET/api/v1/node/:nodeId/:version/notes
List all notes on this version.
Query Parameters
?limit=NUMBERMax results
?startDate=YYYY-MM-DDFilter from date
?endDate=YYYY-MM-DDFilter to date
POST/api/v1/node/:nodeId/:version/notes
Create a new note. Supports text or file upload via multipart form data.
Text Note β€” JSON Body
{ "content": "Your note text here" }
File Note β€” Multipart Form
content: (file) Content-Type: multipart/form-data
GET/api/v1/node/:nodeId/:version/notes/:noteId
View a single note. Text notes return content; file notes return the file.
PUT/api/v1/node/:nodeId/:version/notes/:noteId
Edit an existing text note. File notes cannot be edited.
Request Body
{ "content": "Updated note text" }
Response
{ "success": true, "_id": "...", "message": "Note updated successfully" }
DELETE/api/v1/node/:nodeId/:version/notes/:noteId
Permanently delete a note.
POST/api/v1/node/:nodeId/:version/notes/:noteId/transfer
Transfer a note to a different node in the same tree. Logs contributions on both source and target.
Request Body
{ "targetNodeId": "destination-node-id", "prestige": 0 }
Response
{ "success": true, "noteId": "...", "from": { "nodeId": "...", "version": 0 }, "to": { "nodeId": "...", "version": 0 } }
GET/api/v1/node/:nodeId/:version/notes/book
Book view β€” all notes in hierarchical format including children nodes.
GET/api/v1/node/:nodeId/:version/notes/editor
Open the full-page note editor for creating a new note.
HTML only. Add ?token=...&html to access.
GET/api/v1/node/:nodeId/:version/notes/:noteId/editor
Open the full-page editor for an existing note.
HTML only. File notes redirect to the view page.
Contributions
GET/api/v1/node/:nodeId/:version/contributions
List all contributions on this node version.
Query Parameters
?limit=NUMBERMax results
?startDate=YYYY-MM-DDFilter from date
?endDate=YYYY-MM-DDFilter to date
Values & Goals
Version-scoped key–value pairs for metrics, automation, and computed state. Keys prefixed with _auto__ are read-only and system-generated.
GET/api/v1/node/:nodeId/:version/values
List all values and goals on this version.
POST/api/v1/node/:nodeId/:version/value
Set a value on this version.
Request Body
{ "key": "revenue", "value": 42000 }
POST/api/v1/node/:nodeId/:version/goal
Set a goal on this version.
Request Body
{ "key": "revenue", "goal": 100000 }
AI Chats
GET/api/v1/node/:nodeId/chats
View AI chat sessions that targeted or modified this node.
Query Parameters
?limit=NUMBERMax sessions to return (default 10, max 10)
?sessionId=IDFilter to a specific session
?startDate=ISOFilter chats after this date
?endDate=ISOFilter chats before this date
🀝 Transactions
Transactions are value trades between two sides. Each side is either a NODE (an internal tree node with key–value pairs) or OUTSIDE (an external source like a Solana wallet). Approval follows the tree's transaction policy.
How sides work:
β€’ NODE β€” trades node values (key–value pairs). Requires nodeId and versionIndex.
β€’ OUTSIDE β€” represents an external source (e.g. a Solana wallet). Uses sourceType and sourceId. Cannot carry values β€” only the NODE side sends/receives.

Values: valuesA and valuesB are objects mapping value keys to amounts (e.g. { "gold": 100 }). Each side's values represent what that side gives. At least one side must include values. An OUTSIDE side cannot have values.
List & View
GET/api/v1/node/:nodeId/:version/transactions
List all transactions (pending, accepted, and rejected) for this node version.
GET/api/v1/node/:nodeId/:version/transactions/:transactionId
View a single transaction including both sides, traded values, approval groups, and status.
Create
POST/api/v1/node/:nodeId/:version/transactions
Create a new transaction proposal between two sides.
Node ↔ Node Example
{ "sideA.kind": "NODE", "sideA.nodeId": "node-id-A", "versionAIndex": 1, "valuesA": { "gold": 100 }, "sideB.kind": "NODE", "sideB.nodeId": "node-id-B", "versionBIndex": 2, "valuesB": { "wood": 50 } }
Node ↔ Outside (Solana) Example
{ "sideA.kind": "NODE", "sideA.nodeId": "node-id-A", "versionAIndex": 1, "valuesA": { "gold": 100 }, "sideB.kind": "OUTSIDE", "sideB.sourceType": "SOLANA", "sideB.sourceId": "So1anaWa11etAddr3ss..." }
Field Reference
sideX.kindNODE or OUTSIDE β€” only one side may be OUTSIDE
sideX.nodeIdRequired when kind is NODE
sideX.sourceTypeExternal source type (currently SOLANA). Used when kind is OUTSIDE
sideX.sourceIdExternal identifier (e.g. Solana wallet address). Used when kind is OUTSIDE
versionXIndexRequired for NODE sides. Side B defaults to latest version if omitted
valuesXObject of { key: amount } that this side gives. OUTSIDE sides cannot have values
Self-trades (same node + same version on both sides) are not allowed. If all approval groups resolve immediately, the transaction executes on creation.
Approve & Deny
Approval follows the tree's transaction policy (set via POST /api/v1/root/:rootId/transaction-policy). Depending on the policy, one or more approvals may be needed. Status transitions: pending β†’ accepted or rejected.
POST/api/v1/node/:nodeId/:version/transactions/:transactionId/approve
Approve a pending transaction. When enough approvals are collected (per policy), the transaction executes and values are exchanged.
POST/api/v1/node/:nodeId/:version/transactions/:transactionId/deny
Deny a pending transaction. Sets the transaction status to rejected.
πŸ’Ž Solana Wallet
Each node version can have an associated Solana wallet. Balances are stored in lamports. Auto values like _auto__sol update automatically on read.
GET/api/v1/node/:nodeId/:version/values/solana
Get wallet address, SOL balance, and token balances.
POST/api/v1/node/:nodeId/:version/values/solana
Create or configure the wallet for this version.
POST/api/v1/node/:nodeId/:version/values/solana/send
Send SOL to another address.
Request Body
{ "destination": "So1anaAddr3ss...", "amount": 1000000 }
Amount is in lamports (1 SOL = 1,000,000,000 lamports).
POST/api/v1/node/:nodeId/:version/values/solana/transaction
Execute a token swap via Jupiter aggregator.
Request Body
{ "fromType": "sol | token", "toType": "sol | token", "amount": 500000000, "inputMint": "optional-mint-address", "outputMint": "optional-mint-address", "slippageBps": 50 }
If type is SOL, amount is in lamports. If type is token, amount is the UI amount (human-readable).
πŸ“ Blog
Public endpoints for reading blog posts. No authentication required.
GET/api/v1/blog/posts
List all published blog posts, sorted by newest first.
Response
{ "success": true, "posts": [ { "title": "Why I Built Tree", "slug": "why-i-built-tree", "summary": "...", "publishedAt": "2026-03-15T...", "authorName": "tabor" } ] }
GET/api/v1/blog/posts/:slug
Get a single published blog post by its slug, including full content.
Response
{ "success": true, "post": { "title": "Why I Built Tree", "slug": "why-i-built-tree", "content": "<p>Full HTML content...</p>", "summary": "...", "publishedAt": "2026-03-15T...", "authorName": "tabor" } }