Skip to main content
Folders organize the sources of a project. A folder is a /-separated path such as Contracts/2026; every source is either in one folder or at the top level (""). The methods on this page list, create, rename, remove and delete folders, and move sources between them. Folders also appear on other methods:
Folders are available on the REST API today. In the SDKs they land in the next releases: Python graphor 0.28.0, TypeScript graphor 0.25.0 and the MCP package graphor-mcp 0.25.0. The folder methods, parameters and response fields shown for the SDKs need those versions or later; the hosted remote MCP server offers the folder tools once it runs graphor-mcp 0.25.0.
The rules for paths, the top level and the error codes are the REST API’s: see Folders in the API reference. The SDKs do not check paths themselves; they send the value and raise the API’s error.

Method overview

List folders

Returns every folder of the project: folders created empty, folders that hold sources and folders that uploads are on their way to, each with the folders above it, sorted. At most 10,000 are returned; truncated is true when the project has more.

Create a folder

Creates a folder, and the folders above it, that stays listed while it is empty. Safe to repeat: created is false when it already existed. You do not need to create a folder before uploading or moving into it.

Rename or move a folder

Renames a folder, or moves it under another folder, with its sources and subfolders. With merge, a folder that already exists at new_folder is merged instead of refused.

Remove a folder

Removes a folder and moves its sources and subfolders into the folder above it (the top level for a top-level folder). With merge, a subfolder that lands on a folder of the same name is merged instead of refused.

Delete an empty folder

Deletes a folder that holds no source, with the empty folders below it. Move or delete its sources first.

Move sources

Moves 1 to 1,000 sources to a folder; "" or "/" is the top level. A folder that does not exist is created. Ids that match no source of the project come back in not_found. Safe to repeat.

Retries

rename_folder, remove_folder and delete_folder (renameFolder, removeFolder, deleteFolder) never retry on their own, whatever max_retries / maxRetries says on the client or on the call. After a 503, a timeout or a lost connection the change may have been saved, and a repeated call would answer NotFoundError with code folder.not_found. Before repeating one of them yourself, call list_folders and check whether the change is already there. list_folders, create_folder and move are safe to repeat and follow the client’s retry setting. Folder conflicts (409) are never retried: the API marks them as final.

Error handling

Errors are the SDK’s usual status errors. The API’s code is in the error body: e.body["code"] in Python, err.error.code in TypeScript.
The full list of codes, with what each means, is in Folders: Error codes.

When the API does not apply a folder

The SDK never returns a result whose folder filter or scope the API did not apply. It raises FolderScopeNotAppliedError instead (exported from graphor in both SDKs; a subclass of GraphorError, not an HTTP status error, and never retried). This happens only against an API without folder support, for example an older or separate deployment. Its parameter says what was not applied, and after ask it also carries the conversation id (conversation_id in Python, conversationId in TypeScript). It is raised by: After FolderScopeNotAppliedError on ask, the API has already answered the question in its conversation, unscoped. Repeat the question with reset=True (reset: true) or without conversation_id, so the next answer does not build on it. A direct ingest_file (small files) and ingest_url, ingest_github, ingest_youtube are not checked, because the source is already created when the response arrives; on an API without folder support they land at the top level. Check where they landed with list(folder=...). The checks run on every parsed result, including Python’s with_raw_response / with_streaming_response .parse() (also .parse(to=dict) or a list of dicts) and TypeScript’s .withResponse(). Reading the raw response skips them: Python .read(), .text(), .json(), http_response, or .parse(to=...) into httpx.Response, str, bytes or bytearray; TypeScript .asResponse() (except on the six folder methods, where a missing route is still raised). When a scoped ask or extract fails after the API started streaming, the SDK raises the status error the API reports, with retry_after from the body available as the error’s Retry-After header; in Python this holds in strict response-validation mode too. folders must be a list (Python: a list or a tuple) or an array (TypeScript). Any other value, such as a single string or a set, raises a plain GraphorError before any request is sent.

Example: file sources by year

Next steps

List sources

List the sources of a folder

Ingest sources

Store new sources in a folder

Chat

Ask questions about the sources of a folder

Folders API reference

Paths, the top level, error codes and limits