Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Folders

Folder CRUD plus hierarchical listing and move. Folders group files and subfolders inside a share.

Base path: /api/v1/folders/

Folder metadata shape#

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "id": "fld_01J3I",
  "name": "Engineering",
  "share_id": "shr_01J3H",
  "parent_id": null,
  "path": "/Engineering",
  "owner_id": "usr_01J3N",
  "created_by": "usr_01J3N",
  "created_at": "2026-04-01T10:00:00Z",
  "modified_at": "2026-04-23T10:15:00Z"
}

parent_id: null means the folder is at the share root.

Get folder metadata#

bash
1
2
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/folders/fld_01J3I

Requires READ on the folder.

List folder contents#

bash
1
2
3
curl -G $SCAIDRIVE_URL/api/v1/folders/fld_01J3I/children \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  --data-urlencode "share_id=shr_01J3H"
python
1
2
3
4
5
6
7
8
resp = httpx.get(
    f"{url}/api/v1/folders/fld_01J3I/children",
    headers={"Authorization": f"Bearer {token}"},
    params={"share_id": "shr_01J3H"},
)
contents = resp.json()
for item in contents["items"]:
    print(item["type"], item["name"])
typescript
1
2
3
4
5
6
const params = new URLSearchParams({ share_id: "shr_01J3H" });
const resp = await fetch(
  `${url}/api/v1/folders/fld_01J3I/children?${params}`,
  { headers: { Authorization: `Bearer ${token}` } },
);
const { items } = await resp.json();

Response:

json
1
2
3
4
5
6
7
8
{
  "items": [
    {"id": "fld_01J3J", "name": "Specs", "type": "folder"},
    {"id": "fil_01J3K", "name": "spec.pdf", "type": "file", "size": 48293, "mime_type": "application/pdf", "modified_at": "2026-04-23T10:15:00Z"}
  ],
  "path": "/Engineering",
  "total": 2
}

Query parameters:

Param Default Notes
share_id required The share this folder is in
include_deleted false Include soft-deleted items (for trash views)

Items are a mixed array of files and folders. Distinguish by type.

Listing the share root#

To list the root of a share (top-level folders and files):

bash
1
2
3
curl -G $SCAIDRIVE_URL/api/v1/folders/root/children \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  --data-urlencode "share_id=shr_01J3H"

The special folder ID root refers to the share root.

Create a folder#

bash
1
2
3
4
5
6
7
8
curl -X POST $SCAIDRIVE_URL/api/v1/folders \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "share_id": "shr_01J3H",
    "name": "Drafts",
    "parent_id": "fld_01J3I"
  }'

Omit parent_id to create at the share root.

Requires CREATE on the parent folder (or share, for root).

Folder names are unique within their parent. A second folder called Drafts in the same parent returns 409 NAME_CONFLICT.

Rename a folder#

bash
1
2
3
4
curl -X PATCH $SCAIDRIVE_URL/api/v1/folders/fld_01J3J \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Approved Specs"}'

Requires WRITE. The path of the folder and all descendants is recomputed; children all get renamed change-log entries propagated.

Delete a folder#

bash
1
2
curl -X DELETE $SCAIDRIVE_URL/api/v1/folders/fld_01J3J \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"

Soft delete. Descendants (subfolders and files) are recursively soft-deleted.

Permanent delete:

bash
1
2
curl -X DELETE "$SCAIDRIVE_URL/api/v1/folders/fld_01J3J?permanent=true" \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN"

Requires DELETE on the folder and all its descendants. If the caller lacks DELETE on any descendant, the operation fails atomically — partial deletion is never left behind.

Move a folder#

bash
1
2
3
4
curl -X POST $SCAIDRIVE_URL/api/v1/folders/fld_01J3J/move \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"target_parent_id": "fld_01J4A"}'

Or move to another share:

json
1
{"target_share_id": "shr_01J4Z"}

Moving a folder moves everything inside. Requires DELETE on source, CREATE on target, plus READ on the entire subtree. Cross-share moves trigger a permission re-evaluation for descendants — ACLs inherited from the old parent are replaced by ACLs inherited from the new parent.

Walking a tree#

To list an entire subtree, traverse recursively. There's no single-call "give me everything under this folder" endpoint on purpose — large subtrees would produce unbounded responses and time out. Instead:

python
1
2
3
4
5
6
7
8
9
def walk_folder(client, folder_id, share_id):
    resp = client.get(
        f"/api/v1/folders/{folder_id}/children",
        params={"share_id": share_id},
    )
    for item in resp.json()["items"]:
        yield item
        if item["type"] == "folder":
            yield from walk_folder(client, item["id"], share_id)

If you need the whole share for caching/indexing, consume the sync changelog from cursor 0 — it yields every resource in order, once, with no pagination issues. See Sync Model.

Error cases#

Code When
NOT_FOUND Folder doesn't exist or caller can't see it
NAME_CONFLICT Sibling with same name exists
AUTHZ_PERMISSION_DENIED Missing required permission (including on descendants during delete/move)
INVALID_PATH Name contains disallowed characters (/, \0, leading/trailing whitespace)
RESOURCE_DELETED Folder is soft-deleted

What's next#

Updated 2026-05-18 15:04:13 View source (.md) rev 2