---
title: "Workspaces API: workspaces, files and memory"
description: "Halo HTTP API for workspaces and files: create, reorder and delete workspaces, change their settings and memory, and browse and read their files."
type: "reference"
audience: ["developer"]
lang: "en"
canonical: "https://hello-halo.cc/docs/en/developers/api/workspace.html"
last_updated: "2026-10-19T00:11:17+08:00"
source: "Halo 3.0.4 docs"
---
# 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](https://hello-halo.cc/docs/en/developers/quickstart.html); base URL, authentication and error conventions are in the [HTTP API overview](https://hello-halo.cc/docs/en/developers/api/).

| Operation | Endpoint |
| --- | --- |
| [Set which space a digital human starts new work in](https://hello-halo.cc/docs/en/developers/api/digital-human.html#post-api-apps-appid-move-space) (Digital Humans) | `POST /api/apps/:appId/move-space` |
| [Read one file from a space](#get-api-artifacts-content) | `GET /api/artifacts/content` |
| [Detect whether a file is text or binary and how it would be viewed](#get-api-artifacts-detect-type) | `GET /api/artifacts/detect-type` |
| [Overwrite a file's content](#post-api-artifacts-save) | `POST /api/artifacts/save` |
| [List all spaces](#get-api-spaces) | `GET /api/spaces` |
| [Create a space](#post-api-spaces) | `POST /api/spaces` |
| [Read one space](#get-api-spaces-spaceid) | `GET /api/spaces/:spaceId` |
| [Rename a space or change its icon](#put-api-spaces-spaceid) | `PUT /api/spaces/:spaceId` |
| [Delete a space and everything inside it](#delete-api-spaces-spaceid)  (Irreversible) | `DELETE /api/spaces/:spaceId` |
| [List files and folders in a space](#get-api-spaces-spaceid-artifacts) | `GET /api/spaces/:spaceId/artifacts` |
| [Move a file or folder to the trash](#delete-api-spaces-spaceid-artifacts) | `DELETE /api/spaces/:spaceId/artifacts` |
| [Load one folder's children in the file tree](#post-api-spaces-spaceid-artifacts-children) | `POST /api/spaces/:spaceId/artifacts/children` |
| [Create a new file in a space](#post-api-spaces-spaceid-artifacts-file) | `POST /api/spaces/:spaceId/artifacts/file` |
| [Create a new folder in a space](#post-api-spaces-spaceid-artifacts-folder) | `POST /api/spaces/:spaceId/artifacts/folder` |
| [Move a file or folder to a different directory](#post-api-spaces-spaceid-artifacts-move) | `POST /api/spaces/:spaceId/artifacts/move` |
| [Search file and folder paths in a space by name](#get-api-spaces-spaceid-artifacts-query) | `GET /api/spaces/:spaceId/artifacts/query` |
| [Resync the file list with what is actually on disk](#post-api-spaces-spaceid-artifacts-reconcile) | `POST /api/spaces/:spaceId/artifacts/reconcile` |
| [Rename a file or folder](#post-api-spaces-spaceid-artifacts-rename) | `POST /api/spaces/:spaceId/artifacts/rename` |
| [Get the full lazy-loadable file tree for a space](#get-api-spaces-spaceid-artifacts-tree) | `GET /api/spaces/:spaceId/artifacts/tree` |
| [Read the state of a space's memory](#get-api-spaces-spaceid-memory) | `GET /api/spaces/:spaceId/memory` |
| [Consolidate a space's memory now](#post-api-spaces-spaceid-memory-consolidate) | `POST /api/spaces/:spaceId/memory/consolidate` |
| [Get a space working directory path](#post-api-spaces-spaceid-open) | `POST /api/spaces/:spaceId/open` |
| [Read a space's preferences (layout, memory settings)](#get-api-spaces-spaceid-preferences) | `GET /api/spaces/:spaceId/preferences` |
| [Change a space's preferences, e.g. turn its shared memory on or off](#put-api-spaces-spaceid-preferences) | `PUT /api/spaces/:spaceId/preferences` |
| [Point a space at another working directory](#put-api-spaces-spaceid-working-dir) | `PUT /api/spaces/:spaceId/working-dir` |
| [Read the directory new spaces are created under](#get-api-spaces-default-path) | `GET /api/spaces/default-path` |
| [Read the built-in temporary space](#get-api-spaces-halo) | `GET /api/spaces/halo` |
| [Set the display order of spaces](#put-api-spaces-reorder) | `PUT /api/spaces/reorder` |

## Read one file from a space {#get-api-artifacts-content}

`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}

`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}

`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}

`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`](#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}

`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}

`GET /api/spaces/:spaceId`  (Assistant)

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`PUT /api/spaces/:spaceId`  (Reversible)  (Assistant)

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`DELETE /api/spaces/:spaceId`  (Irreversible)  (Assistant)

::: danger 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**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`GET /api/spaces/:spaceId/artifacts`  (Assistant)

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

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`DELETE /api/spaces/:spaceId/artifacts`  (Reversible)  (Assistant)

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`POST /api/spaces/:spaceId/artifacts/children`  (Assistant)

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`POST /api/spaces/:spaceId/artifacts/file`  (Reversible)  (Assistant)

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`POST /api/spaces/:spaceId/artifacts/folder`  (Assistant)

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`POST /api/spaces/:spaceId/artifacts/move`  (Reversible)  (Assistant)

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`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**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`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**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`POST /api/spaces/:spaceId/artifacts/rename`  (Reversible)  (Assistant)

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`GET /api/spaces/:spaceId/artifacts/tree`  (Assistant)

- Folder nodes may have childrenLoaded:false — call [`POST /api/spaces/:spaceId/artifacts/children`](#post-api-spaces-spaceid-artifacts-children) to load their contents.

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`GET /api/spaces/:spaceId/memory`  (Assistant)

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`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**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`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**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`GET /api/spaces/:spaceId/preferences`  (Assistant)

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

**Path parameters**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`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**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`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**

| Name | Description |
| --- | --- |
| `spaceId` | Workspace id, from [`GET /api/spaces`](#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}

`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}

`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`](#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}

`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`](#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>"]}'
```
