[GH-ISSUE #4818] [FEAT]: Expand API to list all folders in a workspace #3035

Closed
opened 2026-02-22 18:32:21 -05:00 by yindo · 4 comments
Owner

Originally created by @rainer-arc46 on GitHub (Jan 1, 2026).
Original GitHub issue: https://github.com/Mintplex-Labs/anything-llm/issues/4818

What would you like to see?

I am building a pipeline that automatically updates embedded docs whenever a new docusaurus build is triggered.

Everything is working fine.
I'm uploading new documents to a timestamped folder.
I'm deleting all folders in my namespace that are no longer current.

The problem (and feature request) is that the only way I have found to get a list of all folders in a workspace is by way of /workspace/slug and then parsing the returned docs, extracting the folder name from "docpath" entries.

While this will work, there has to be a better way, right? :-)

If I was just to stupid to find an existing solution, please feel free to say so...

Originally created by @rainer-arc46 on GitHub (Jan 1, 2026). Original GitHub issue: https://github.com/Mintplex-Labs/anything-llm/issues/4818 ### What would you like to see? I am building a pipeline that automatically updates embedded docs whenever a new docusaurus build is triggered. Everything is working fine. I'm uploading new documents to a timestamped folder. I'm deleting all folders in my namespace that are no longer current. The problem (and feature request) is that the only way I have found to get a list of all folders in a workspace is by way of /workspace/slug and then parsing the returned docs, extracting the folder name from "docpath" entries. While this will work, there has to be a better way, right? :-) If I was just to stupid to find an existing solution, please feel free to say so...
yindo added the enhancementfeature request labels 2026-02-22 18:32:21 -05:00
yindo closed this issue 2026-02-22 18:32:21 -05:00
Author
Owner

@timothycarambat commented on GitHub (Jan 2, 2026):

You should be able to see folders from /v1/documents no?

{
  "localFiles": {
    "name": "documents",
    "type": "folder",
    "items": [
      {
        "name": "my-stored-document.json",
        "type": "file",
        "id": "bb07c334-4dab-4419-9462-9d00065a49a1",
        "url": "file://my-stored-document.txt",
        "title": "my-stored-document.txt",
        "cached": false
      }
    ]
  }
}

If you delete a document/folder from the main filesystem we will automatically un-embed the source documents from any workspaces as well. Does that work?

@timothycarambat commented on GitHub (Jan 2, 2026): You should be able to see folders from `/v1/documents` no? ```json { "localFiles": { "name": "documents", "type": "folder", "items": [ { "name": "my-stored-document.json", "type": "file", "id": "bb07c334-4dab-4419-9462-9d00065a49a1", "url": "file://my-stored-document.txt", "title": "my-stored-document.txt", "cached": false } ] } } ``` If you delete a document/folder from the main filesystem we will automatically un-embed the source documents from any workspaces as well. Does that work?
Author
Owner

@rainer-arc46 commented on GitHub (Jan 3, 2026):

Hi @timothycarambat ,

thank you for your response, but I would kindly ask you to reconsider your closing of this issue.

/v1/documents will give me all folder, without the workspace. As I have multiple workspaces, I need only the folders used in one specific workspace. And even if v1/documents would give me information concerning the workspace, it would still seem like a slight overkill to retrieve potentially thousands, if not more, document metadata to retrieve 1-2 folder names.

In order to retrieve all folder connected to a specific workspcace I am currently doing

    const endpoint = `${API_BASE_URL}/api/v1/workspace/${WORKSPACE_SLUG}`;
    const response = await fetch(endpoint, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${API_KEY}`
      }
    });
    const workspaceResponse = await response.json() as WorkspaceResponse;
    // ...
    const workspace = workspaceResponse.workspace[0];
    const documents = workspace.documents;

    // folder here
    const folder = documents.map((doc) => {
      const docPath = doc.docpath;
      return docPath.split('/')[0];
    }).reduce((folder: Set<string>, folderName: string) => {
      folder.add(folderName);
      return folder;
    }, new Set<string>());

This obviously "works", but I'm iterating over currently hundreds of elements in order to retrieve usually only 2 values.

The un-embedding part is what I am using. Instead of removing docs individually, I just remove the folder.

Continuation of code above

    for (const folderName of folder) {
      if (folderName === FOLDER_NAME || folderName === 'custom-documents') {
        console.log("Ignoring folder: " + folderName + "")
        continue;
      }
      console.log(`Deleting folder: ${folderName}`);
      const endpoint = `${API_BASE_URL}/api/v1/document/remove-folder`;
      await fetch(endpoint, {
        method: 'DELETE',
        headers: {
          'Authorization': `Bearer ${API_KEY}`
        },
        body: JSON.stringify({name: folderName}),
      });
    }
@rainer-arc46 commented on GitHub (Jan 3, 2026): Hi @timothycarambat , thank you for your response, but I would kindly ask you to reconsider your closing of this issue. `/v1/documents` will give me **_all_** folder, **_without_** the workspace. As I have multiple workspaces, I need only the folders used in one specific workspace. And even if `v1/documents` would give me information concerning the workspace, it would still seem like a slight overkill to retrieve potentially thousands, if not more, document metadata to retrieve 1-2 folder names. In order to retrieve all folder connected to a specific workspcace I am currently doing ```typescript const endpoint = `${API_BASE_URL}/api/v1/workspace/${WORKSPACE_SLUG}`; const response = await fetch(endpoint, { method: 'GET', headers: { 'Authorization': `Bearer ${API_KEY}` } }); const workspaceResponse = await response.json() as WorkspaceResponse; // ... const workspace = workspaceResponse.workspace[0]; const documents = workspace.documents; // folder here const folder = documents.map((doc) => { const docPath = doc.docpath; return docPath.split('/')[0]; }).reduce((folder: Set<string>, folderName: string) => { folder.add(folderName); return folder; }, new Set<string>()); ``` This obviously "works", but I'm iterating over currently hundreds of elements in order to retrieve usually only **2** values. The un-embedding part is what I am using. Instead of removing docs individually, I just remove the folder. Continuation of code above ```typescript for (const folderName of folder) { if (folderName === FOLDER_NAME || folderName === 'custom-documents') { console.log("Ignoring folder: " + folderName + "") continue; } console.log(`Deleting folder: ${folderName}`); const endpoint = `${API_BASE_URL}/api/v1/document/remove-folder`; await fetch(endpoint, { method: 'DELETE', headers: { 'Authorization': `Bearer ${API_KEY}` }, body: JSON.stringify({name: folderName}), }); } ```
Author
Owner

@timothycarambat commented on GitHub (Jan 3, 2026):

To be sure I am understanding the core issue.

  • You have folders with many documents
  • When a folder is "stale" you need to remove it from specific workspaces
  • You do this by pinging the workspace, see all the docs, and pluck just the folder out from docpath
  • You can then pass this set into a DELETE

The request is if there as an edit we can make to the documents section to more easily parse out the folder name so you dont need to parse it manually, since you would need to iterate over every document to do form this list currently?

@timothycarambat commented on GitHub (Jan 3, 2026): To be sure I am understanding the core issue. - You have folders with many documents - When a folder is "stale" you need to remove it from specific workspaces - You do this by pinging the workspace, see all the docs, and pluck just the folder out from `docpath` - You can then pass this set into a `DELETE` The request is if there as an edit we can make to the `documents` section to more easily parse out the folder name so you dont need to parse it manually, since you would need to iterate over every document to do form this list currently?
Author
Owner

@rainer-arc46 commented on GitHub (Jan 5, 2026):

Correct.

/v1/workspace/{slug}/folders could return an array of all folders associated with a workspace or
/v1/folders could list all folders including the workspace(s) a folder is used in.

I could then retrieve folders directly, without retrieving and parsing all documents in a workspace.

Long story short: folders are not first class citizens in AnythingLLM.


But if you're asking what the core problem is, the answer is actually slightly different. What I described above is a workaround for the fact, that I haven't found a way to update a file in AnythingLLM. Uploading the exact same file twice results in two entries in a folder.

The whole "upload everything in a separate folder and delete all other, obsolete folder" is just a workaround.

If we could add a client side defined identifier, e.g. filename+hash, that would be returned with

/v1/workspace/{slug}

then we could check for changes before we upload to AnythingLLM and identify any documents no longer relevant.

We could then selectively add/delete files.

(But this would be a separate issue.)

Uploading the exact same file twice results in:
Different names.
Different ids.
Same URL?

{
  "folder": "custom-documents",
  "documents": [
    {
      "name": "websites.json-4590205b-f95b-4e00-a6a2-eec5aaea3459.json",
      "type": "file",
      "id": "4590205b-f95b-4e00-a6a2-eec5aaea3459",
      "url": "file:///app/collector/hotdir/websites.json",
      "title": "Custom Title",
      "docAuthor": "Author Name",
      "description": "A brief description",
      "docSource": "Source of the document",
      "chunkSource": "",
      "published": "1/5/2026, 9:08:07 AM",
      "wordCount": 221,
      "token_count_estimate": 298,
      "cached": false,
      "pinnedWorkspaces": [],
      "watched": false
    },
    {
      "name": "websites.json-d5df4d92-3b2f-4716-a3b9-503081e0fbc6.json",
      "type": "file",
      "id": "d5df4d92-3b2f-4716-a3b9-503081e0fbc6",
      "url": "file:///app/collector/hotdir/websites.json",
      "title": "Custom Title",
      "docAuthor": "Author Name",
      "description": "A brief description",
      "docSource": "Source of the document",
      "chunkSource": "",
      "published": "1/5/2026, 9:08:22 AM",
      "wordCount": 221,
      "token_count_estimate": 298,
      "cached": false,
      "pinnedWorkspaces": [],
      "watched": false
    }
  ],
  "error": null
}
@rainer-arc46 commented on GitHub (Jan 5, 2026): Correct. `/v1/workspace/{slug}/folders` could return an array of all folders associated with a workspace or `/v1/folders` could list all folders including the workspace(s) a folder is used in. I could then retrieve folders directly, without retrieving and parsing all documents in a workspace. Long story short: folders are not first class citizens in AnythingLLM. ********************************************** But if you're asking what the core problem is, the answer is actually slightly different. What I described above is a workaround for the fact, that I haven't found a way to update a file in AnythingLLM. Uploading the exact same file twice results in two entries in a folder. The whole "_upload everything in a separate folder and delete all other, obsolete folder_" is just a workaround. If we could add a **_client side_** defined identifier, e.g. filename+hash, that would be returned with `/v1/workspace/{slug}` then we could check for changes before we upload to AnythingLLM and identify any documents no longer relevant. We could then selectively add/delete files. (But this would be a separate issue.) Uploading the exact same file twice results in: Different names. Different ids. **Same URL?** ``` json { "folder": "custom-documents", "documents": [ { "name": "websites.json-4590205b-f95b-4e00-a6a2-eec5aaea3459.json", "type": "file", "id": "4590205b-f95b-4e00-a6a2-eec5aaea3459", "url": "file:///app/collector/hotdir/websites.json", "title": "Custom Title", "docAuthor": "Author Name", "description": "A brief description", "docSource": "Source of the document", "chunkSource": "", "published": "1/5/2026, 9:08:07 AM", "wordCount": 221, "token_count_estimate": 298, "cached": false, "pinnedWorkspaces": [], "watched": false }, { "name": "websites.json-d5df4d92-3b2f-4716-a3b9-503081e0fbc6.json", "type": "file", "id": "d5df4d92-3b2f-4716-a3b9-503081e0fbc6", "url": "file:///app/collector/hotdir/websites.json", "title": "Custom Title", "docAuthor": "Author Name", "description": "A brief description", "docSource": "Source of the document", "chunkSource": "", "published": "1/5/2026, 9:08:22 AM", "wordCount": 221, "token_count_estimate": 298, "cached": false, "pinnedWorkspaces": [], "watched": false } ], "error": null } ```
yindo changed title from [FEAT]: Expand API to list all folders in a workspace to [GH-ISSUE #4818] [FEAT]: Expand API to list all folders in a workspace 2026-06-05 14:49:58 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Mintplex-Labs/anything-llm#3035