Sign in Get started

Folders

Inspect a project's virtual folder tree (read-only) — list folders, fetch the nested tree, and get per-folder image stats.

View as Markdown

Pictograph organizes a project’s images into virtual folders. The folders are virtual: GCS object paths never move, so a folder is just a virtual_folder_path label on the image rows. The developer API exposes the read side (list, tree, stats); folder mutations (create, rename, delete) stay in the web app for now. A cross-org project id returns a 404, consistent with the other developer resources.

from pictograph import Client
client = Client()  # reads PICTOGRAPH_API_KEY

list

List a project’s folders. Pass parent_path to return only the direct children of a folder (use "" for the root-level folders); omit it to return every folder in the project.

ArgTypeDefaultNotes
project_idstrrequiredThe project (dataset) UUID
parent_pathstr | NoneNoneNone returns all folders; "" returns root-level only; a path returns that folder’s direct children
all_folders = client.folders.list("project-uuid")
top_level = client.folders.list("project-uuid", parent_path="")
for f in all_folders:
    print(f.full_path, f.image_count)
# All folders in the project:
curl -s "https://api.pictograph.io/api/v1/developer/folders/list/project-uuid" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

# Direct children of the root only:
curl -s "https://api.pictograph.io/api/v1/developer/folders/list/project-uuid?parent_path=" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

Returns list[Folder].

tree

Fetch the project’s folder hierarchy as a nested tree (each node carries its children). Handy for rendering a folder sidebar in one request rather than walking list level by level.

tree = client.folders.tree("project-uuid")
for node in tree:
    print(node.name, len(node.children))
curl -s "https://api.pictograph.io/api/v1/developer/folders/tree/project-uuid" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

Returns list[FolderTreeNode] (the root-level nodes, with children nested).

stats

Image statistics for a single folder, by default including its subfolders.

ArgTypeDefaultNotes
folder_idstrrequiredThe folder UUID
include_subfoldersboolTrueWhen True, roll up the folder’s subfolders too
stats = client.folders.stats("folder-uuid", include_subfolders=True)
print(stats.total_images, stats.total_folders, stats.total_size_bytes)
curl -s "https://api.pictograph.io/api/v1/developer/folders/folder-uuid/stats?include_subfolders=true" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

Returns FolderStats.

create

Create a virtual folder (idempotent — creating an existing path returns it). Parents are auto-created, the same way an upload into a folder_path does — use this to pre-stage an empty folder structure ahead of uploads. Requires member+ role.

folder = client.folders.create(dataset.id, "/train/positive")
print(folder.id, folder.full_path)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/folders/" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" -H "Content-Type: application/json" \
  -d '{"dataset_id": "<dataset-uuid>", "folder_path": "/train/positive"}'

pictograph folders create <dataset-uuid> /train/positive

Returns the folder in the canonical shape: {"data": {id, dataset_id, name, folder_path, parent_folder_id, image_count, created_at}}.

rename

Rename a folder — the folder row, every descendant folder’s path, and every contained image’s folder path move together in one call (storage paths are immutable; virtual folders are metadata, so no bytes move). A sibling folder with the target name returns 409 ConflictError. Requires member+ role.

folder = client.folders.rename(folder.id, "negatives")
curl -s -X PATCH "https://api.pictograph.io/api/v1/developer/folders/<folder-uuid>/rename" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" -H "Content-Type: application/json" \
  -d '{"new_name": "negatives"}'

pictograph folders rename <folder-uuid> negatives

delete

Delete a folder (cascade=true moves its images to the parent folder first; empty-only otherwise). Requires member+ role.

client.folders.delete(folder.id, cascade=True)

Common errors

StatusExceptionCause
404NotFoundErrorProject or folder id does not exist in your org
403ForbiddenErrorNo access to the organization, or mutations without member+ role
409ConflictErrorrename target name already exists as a sibling folder
Copied to clipboard