Folders
Inspect a project's virtual folder tree (read-only) — list folders, fetch the nested tree, and get per-folder image stats.
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.
| Arg | Type | Default | Notes |
|---|---|---|---|
project_id | str | required | The project (dataset) UUID |
parent_path | str | None | None | None 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.
| Arg | Type | Default | Notes |
|---|---|---|---|
folder_id | str | required | The folder UUID |
include_subfolders | bool | True | When 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
| Status | Exception | Cause |
|---|---|---|
| 404 | NotFoundError | Project or folder id does not exist in your org |
| 403 | ForbiddenError | No access to the organization, or mutations without member+ role |
| 409 | ConflictError | rename target name already exists as a sibling folder |