π€ 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.
π¬ 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 Chinesesummarize this into 30 wordsfind all the places where marketing strategy is mentionedextract every action item and deadlineidentify 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 }
βοΈ 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.
π 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"
}
}