Skip to content

API: Workspaces and files ​

Halo HTTP API for workspaces and files: create, reorder and delete workspaces, change their settings and memory, and browse and read their files.

Workspaces (space in the API) are where Halo works, and each one has a working folder. Use these operations to create and arrange workspaces, change their settings and shared memory, and browse and read the files they hold.

Paths are relative to your Halo base URL, and every request carries the access password. Set $HALO_URL and $HALO_TOKEN as in the quickstart; base URL, authentication and error conventions are in the HTTP API overview.

OperationEndpoint
Set which space a digital human starts new work in (Digital Humans)POST /api/apps/:appId/move-space
Read one file from a spaceGET /api/artifacts/content
Detect whether a file is text or binary and how it would be viewedGET /api/artifacts/detect-type
Overwrite a file's contentPOST /api/artifacts/save
List all spacesGET /api/spaces
Create a spacePOST /api/spaces
Read one spaceGET /api/spaces/:spaceId
Rename a space or change its iconPUT /api/spaces/:spaceId
Delete a space and everything inside it IrreversibleDELETE /api/spaces/:spaceId
List files and folders in a spaceGET /api/spaces/:spaceId/artifacts
Move a file or folder to the trashDELETE /api/spaces/:spaceId/artifacts
Load one folder's children in the file treePOST /api/spaces/:spaceId/artifacts/children
Create a new file in a spacePOST /api/spaces/:spaceId/artifacts/file
Create a new folder in a spacePOST /api/spaces/:spaceId/artifacts/folder
Move a file or folder to a different directoryPOST /api/spaces/:spaceId/artifacts/move
Search file and folder paths in a space by nameGET /api/spaces/:spaceId/artifacts/query
Resync the file list with what is actually on diskPOST /api/spaces/:spaceId/artifacts/reconcile
Rename a file or folderPOST /api/spaces/:spaceId/artifacts/rename
Get the full lazy-loadable file tree for a spaceGET /api/spaces/:spaceId/artifacts/tree
Read the state of a space's memoryGET /api/spaces/:spaceId/memory
Consolidate a space's memory nowPOST /api/spaces/:spaceId/memory/consolidate
Get a space working directory pathPOST /api/spaces/:spaceId/open
Read a space's preferences (layout, memory settings)GET /api/spaces/:spaceId/preferences
Change a space's preferences, e.g. turn its shared memory on or offPUT /api/spaces/:spaceId/preferences
Point a space at another working directoryPUT /api/spaces/:spaceId/working-dir
Read the directory new spaces are created underGET /api/spaces/default-path
Read the built-in temporary spaceGET /api/spaces/halo
Set the display order of spacesPUT /api/spaces/reorder

Read one file from a space ​

GET /api/artifacts/content Assistant

  • Binary types (png, jpg, pdf, zip, …) come back base64-encoded, with encoding: "base64".
  • The content is returned exactly as stored: a .env file or a pasted key comes back in the clear.

Query parameters: path (required)

Response

json
{
  "success": true,
  "data": {
    "content": "…",
    "mimeType": "text/plain",
    "encoding": "utf-8",
    "size": 1234
  }
}

Errors

  • 400 missing path, 403 outside an allowed workspace, 404 not found, 500 "File too large" above 10 MB for text or 50 MB for binary files.

Example

bash
curl -s "$HALO_URL/api/artifacts/content?path=/absolute/path/inside/the/space" \
  -H "Authorization: Bearer $HALO_TOKEN"

Detect whether a file is text or binary and how it would be viewed ​

GET /api/artifacts/detect-type Assistant

  • path is the file's absolute path inside a workspace.

Query parameters: path (required)

Response

json
{
  "success": true,
  "data": {
    "isText": true,
    "canViewInCanvas": true,
    "contentType": "markdown",
    "mimeType": "text/markdown"
  }
}

Errors

  • 403 when the path is outside an allowed workspace, 404 when the file does not exist.

Example

bash
curl -s "$HALO_URL/api/artifacts/detect-type?path=/absolute/path/inside/the/workspace" \
  -H "Authorization: Bearer $HALO_TOKEN"

Overwrite a file's content ​

POST /api/artifacts/save Reversible Assistant

  • Replaces the whole file in place. There is no version history or trash, but you can overwrite it again to correct a mistake.

Request body

json
{
  "path": "/absolute/path/inside/the/space",
  "content": "new file contents"
}

Response

json
{
  "success": true
}

Errors

  • 403 when the path resolves outside an allowed workspace.

Example

bash
curl -sX POST "$HALO_URL/api/artifacts/save" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path":"/absolute/path/inside/the/space","content":"new file contents"}'

List all spaces ​

GET /api/spaces Assistant

  • Lists the workspaces the user created. The Halo Workspace is not in this list; read it with GET /api/spaces/halo.
  • Pass an entry's id wherever an operation takes a spaceId.

Response

json
{
  "success": true,
  "data": [
    {
      "id": "<uuid>",
      "name": "Work",
      "path": "/…"
    }
  ]
}

Example

bash
curl -s "$HALO_URL/api/spaces" \
  -H "Authorization: Bearer $HALO_TOKEN"

Create a space ​

POST /api/spaces Assistant

  • Optional body fields: customPath (put the workspace's folder somewhere other than the default directory) and color. icon is an emoji.

Request body

json
{
  "name": "Product research",
  "icon": "📚"
}

Response

json
{
  "success": true,
  "data": {
    "id": "<uuid>",
    "name": "Product research",
    "path": "/…"
  }
}

Example

bash
curl -sX POST "$HALO_URL/api/spaces" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Product research","icon":"📚"}'

Read one space ​

GET /api/spaces/:spaceId Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Response

json
{
  "success": true,
  "data": {
    "id": "<uuid>",
    "name": "Work",
    "path": "/…"
  }
}

Example

bash
curl -s "$HALO_URL/api/spaces/<spaceId>" \
  -H "Authorization: Bearer $HALO_TOKEN"

Rename a space or change its icon ​

PUT /api/spaces/:spaceId Reversible Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Request body

json
{
  "name": "Renamed space"
}

Response

ts
{"success":true,"data":{...updated space}}

Example

bash
curl -sX PUT "$HALO_URL/api/spaces/<spaceId>" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Renamed space"}'

Delete a space and everything inside it ​

DELETE /api/spaces/:spaceId Irreversible Assistant

Irreversible

This cannot be undone, and nothing goes to a trash folder. Make sure it is what the user wants before you call it.

  • Deletes the space folder recursively, every conversation in it, and every digital human installed in it.
  • Nothing is moved to a trash folder and there is no undo.
  • Name what will be lost and get the user to agree before running this.

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Response

json
{
  "success": true
}

Example

bash
curl -sX DELETE "$HALO_URL/api/spaces/<spaceId>" \
  -H "Authorization: Bearer $HALO_TOKEN"

List files and folders in a space ​

GET /api/spaces/:spaceId/artifacts Assistant

  • Optional query param maxDepth (default 2) controls how many directory levels deep to list.

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Query parameters: maxDepth

Response

json
{
  "success": true,
  "data": [
    {
      "id": "…",
      "name": "report.md",
      "type": "file",
      "path": "/…",
      "relativePath": "report.md",
      "extension": "md",
      "size": 1024
    }
  ]
}

Example

bash
curl -s "$HALO_URL/api/spaces/<spaceId>/artifacts" \
  -H "Authorization: Bearer $HALO_TOKEN"

Move a file or folder to the trash ​

DELETE /api/spaces/:spaceId/artifacts Reversible Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Request body

json
{
  "path": "/absolute/path/inside/the/space"
}

Response

json
{
  "success": true
}

Errors

  • 400 if path is missing. Goes to the OS trash (recoverable there), not deleted outright.

Example

bash
curl -sX DELETE "$HALO_URL/api/spaces/<spaceId>/artifacts" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path":"/absolute/path/inside/the/space"}'

Load one folder's children in the file tree ​

POST /api/spaces/:spaceId/artifacts/children Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Request body

json
{
  "dirPath": "/absolute/path/inside/the/space"
}

Response

json
{
  "success": true,
  "data": [
    {
      "id": "…",
      "name": "index.ts",
      "type": "file"
    }
  ]
}

Errors

  • 400 if dirPath is missing. 403 if dirPath resolves outside this space's working directory.

Example

bash
curl -sX POST "$HALO_URL/api/spaces/<spaceId>/artifacts/children" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"dirPath":"/absolute/path/inside/the/space"}'

Create a new file in a space ​

POST /api/spaces/:spaceId/artifacts/file Reversible Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Request body

json
{
  "parentPath": "",
  "name": "notes.md",
  "content": "# Notes"
}

Response

json
{
  "success": true,
  "data": {
    "path": "/…/notes.md"
  }
}

Errors

  • 400 if name is missing. parentPath and content are optional — an empty parentPath creates the file at the space root, content defaults to empty. If a file already exists at that path, it is silently overwritten.

Example

bash
curl -sX POST "$HALO_URL/api/spaces/<spaceId>/artifacts/file" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"parentPath":"","name":"notes.md","content":"# Notes"}'

Create a new folder in a space ​

POST /api/spaces/:spaceId/artifacts/folder Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Request body

json
{
  "parentPath": "",
  "name": "assets"
}

Response

json
{
  "success": true,
  "data": {
    "path": "/…/assets"
  }
}

Errors

  • 400 if name is missing. parentPath is optional — omit it to create at the space root.

Example

bash
curl -sX POST "$HALO_URL/api/spaces/<spaceId>/artifacts/folder" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"parentPath":"","name":"assets"}'

Move a file or folder to a different directory ​

POST /api/spaces/:spaceId/artifacts/move Reversible Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Request body

json
{
  "oldPath": "/absolute/path/inside/the/space/file.md"
}

Response

json
{
  "success": true,
  "data": {
    "path": "/…/new-location/file.md"
  }
}

Errors

  • 400 if oldPath is missing. newParentPath is optional — omit it to move to the space root.

Example

bash
curl -sX POST "$HALO_URL/api/spaces/<spaceId>/artifacts/move" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"oldPath":"/absolute/path/inside/the/space/file.md"}'

Search file and folder paths in a space by name ​

GET /api/spaces/:spaceId/artifacts/query Assistant

  • Returns only the best matches (limit defaults to 50). indexing:true means the space is still being indexed and a repeated query may find more; truncated:true means the space has more paths than the index holds.

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Query parameters: q (required), limit (required)

Response

json
{
  "success": true,
  "data": {
    "items": [
      {
        "name": "report.md",
        "type": "file",
        "path": "/…",
        "relativePath": "docs/report.md"
      }
    ],
    "truncated": false,
    "indexing": false
  }
}

Example

bash
curl -s "$HALO_URL/api/spaces/<spaceId>/artifacts/query?q=report&limit=50" \
  -H "Authorization: Bearer $HALO_TOKEN"

Resync the file list with what is actually on disk ​

POST /api/spaces/:spaceId/artifacts/reconcile Assistant

  • Use after files changed on disk outside of Halo (e.g. via a terminal command) and the file list looks stale.

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Response

json
{
  "success": true
}

Example

bash
curl -sX POST "$HALO_URL/api/spaces/<spaceId>/artifacts/reconcile" \
  -H "Authorization: Bearer $HALO_TOKEN"

Rename a file or folder ​

POST /api/spaces/:spaceId/artifacts/rename Reversible Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Request body

json
{
  "oldPath": "/absolute/path/old-name.md",
  "newName": "new-name.md"
}

Response

json
{
  "success": true
}

Errors

  • 400 if oldPath or newName is missing. Fails if a file already exists at the new name.

Example

bash
curl -sX POST "$HALO_URL/api/spaces/<spaceId>/artifacts/rename" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"oldPath":"/absolute/path/old-name.md","newName":"new-name.md"}'

Get the full lazy-loadable file tree for a space ​

GET /api/spaces/:spaceId/artifacts/tree Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Response

json
{
  "success": true,
  "data": {
    "workspaceRoot": "/…",
    "nodes": [
      {
        "id": "…",
        "name": "src",
        "type": "folder",
        "childrenLoaded": false
      }
    ]
  }
}

Example

bash
curl -s "$HALO_URL/api/spaces/<spaceId>/artifacts/tree" \
  -H "Authorization: Bearer $HALO_TOKEN"

Read the state of a space's memory ​

GET /api/spaces/:spaceId/memory Assistant

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Response

json
{
  "success": true,
  "data": {
    "exists": true,
    "totalBytes": 48213,
    "topicCount": 7,
    "lastConsolidatedAt": "2026-09-26T08:00:00.000Z",
    "lastAttempt": {
      "at": "…",
      "outcome": "committed"
    },
    "consolidating": false
  }
}

Example

bash
curl -s "$HALO_URL/api/spaces/<spaceId>/memory" \
  -H "Authorization: Bearer $HALO_TOKEN"

Consolidate a space's memory now ​

POST /api/spaces/:spaceId/memory/consolidate Reversible Assistant

  • Returns once started; the work runs in the background and uses the model. started:false with reason "already-running" or "empty". Every consolidation keeps a restorable snapshot.

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Response

json
{
  "success": true,
  "data": {
    "started": true
  }
}

Example

bash
curl -sX POST "$HALO_URL/api/spaces/<spaceId>/memory/consolidate" \
  -H "Authorization: Bearer $HALO_TOKEN"

Get a space working directory path ​

POST /api/spaces/:spaceId/open Assistant

  • Returns the path only. It opens nothing — use this to find where a space keeps its files.

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Response

json
{
  "success": true,
  "data": {
    "path": "/Users/me/HaloSpaces/work"
  }
}

Example

bash
curl -sX POST "$HALO_URL/api/spaces/<spaceId>/open" \
  -H "Authorization: Bearer $HALO_TOKEN"

Read a space's preferences (layout, memory settings) ​

GET /api/spaces/:spaceId/preferences Assistant

  • Absent memory fields mean the defaults: memory on, auto-consolidation on, cadence "diligent".

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Response

json
{
  "success": true,
  "data": {
    "memory": {
      "enabled": true,
      "autoConsolidate": true,
      "cadence": "diligent"
    }
  }
}

Example

bash
curl -s "$HALO_URL/api/spaces/<spaceId>/preferences" \
  -H "Authorization: Bearer $HALO_TOKEN"

Change a space's preferences, e.g. turn its shared memory on or off ​

PUT /api/spaces/:spaceId/preferences Reversible Assistant

  • Merged into what is stored. memory.enabled turns the memory shared by the space's conversations on/off (files are kept); memory.autoConsolidate turns automatic consolidation on/off; memory.cadence is "diligent", "balanced" or "economical". Applies to new conversations.

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Request body

json
{
  "memory": {
    "enabled": false
  }
}

Response

ts
{"success":true,"data":{...updated space}}

Example

bash
curl -sX PUT "$HALO_URL/api/spaces/<spaceId>/preferences" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"memory":{"enabled":false}}'

Point a space at another working directory ​

PUT /api/spaces/:spaceId/working-dir Reversible Assistant

  • Points the workspace at another existing folder, given by its full path. Nothing is moved, created or deleted, and conversations keep their history.
  • The workspace's Digital Humans work in the new folder too, and files they send come from there, so confirm the change with the user.
  • The folder must exist and lie outside Halo's and the agent engine's own data folders. The Halo Workspace cannot be changed.
  • Refused while a reply, run or background task is in progress in the workspace, or while another change to it is under way.

Path parameters

NameDescription
spaceIdWorkspace id, from GET /api/spaces. The Halo Workspace is always halo-temp.

Request body

json
{
  "workingDir": "/absolute/path/to/existing/folder"
}

Response

ts
{"success":true,"data":{...updated space}} | {"success":false,"error":"That folder does not exist."}

Example

bash
curl -sX PUT "$HALO_URL/api/spaces/<spaceId>/working-dir" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"workingDir":"/absolute/path/to/existing/folder"}'

Read the directory new spaces are created under ​

GET /api/spaces/default-path Assistant

Response

json
{
  "success": true,
  "data": "/Users/me/HaloSpaces"
}

Example

bash
curl -s "$HALO_URL/api/spaces/default-path" \
  -H "Authorization: Bearer $HALO_TOKEN"

Read the built-in temporary space ​

GET /api/spaces/halo Assistant

  • The scratch space behind Halo's temporary sessions. Its id is the fixed string "halo-temp", not a uuid, and it always exists — but GET /api/spaces leaves it out, so it is reachable only through this route.

Response

json
{
  "success": true,
  "data": {
    "id": "halo-temp",
    "name": "Halo",
    "path": "/…",
    "isTemp": true
  }
}

Example

bash
curl -s "$HALO_URL/api/spaces/halo" \
  -H "Authorization: Bearer $HALO_TOKEN"

Set the display order of spaces ​

PUT /api/spaces/reorder Reversible Assistant

  • Send every workspace id, in the new order. A partial list leaves the others out of order, so read the full list with GET /api/spaces first and reorder that.

Request body

json
{
  "spaceIds": [
    "<uuid>",
    "<uuid>",
    "<uuid>"
  ]
}

Response

json
{
  "success": true
}

Example

bash
curl -sX PUT "$HALO_URL/api/spaces/reorder" \
  -H "Authorization: Bearer $HALO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"spaceIds":["<uuid>","<uuid>","<uuid>"]}'

基于 MIT 协议开源 · Open source under the MIT license