Folders
Using folders to organize entities hierarchically within collections.
Overview
Folders provide hierarchical organization within a collection. They use contains/in bidirectional relationship pairs to form a tree structure. Like all things in Arke, folders are just entities—managed through the standard entity API.
Creating a Folder
POST /entities
Content-Type: application/json
Authorization: Bearer <token>
{
"type": "folder",
"properties": {
"label": "Pequod Crew Profiles",
"description": "Profiles of all crew members aboard the Pequod"
},
"relationships": [
{ "predicate": "in", "peer": "01KPARENT789ABCDEFGHJKMNPQ", "peer_type": "folder" }
],
"collection": "01KFNR0H0Q791Y1SMZWEQ09FGV"
}Response:
{
"id": "01KFOLDER123ABCDEFGHJKMNPQ",
"cid": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy",
"type": "folder",
"properties": {
"label": "Pequod Crew Profiles",
"description": "Profiles of all crew members aboard the Pequod"
},
"relationships": [
{ "predicate": "collection", "peer": "01KFNR0H0Q791Y1SMZWEQ09FGV", "peer_type": "collection" },
{ "predicate": "in", "peer": "01KPARENT789ABCDEFGHJKMNPQ", "peer_type": "folder" }
],
"ver": 1,
"created_at": "2025-01-15T10:00:00.000Z",
"ts": 1736937600000,
"edited_by": { "user_id": "01JCAPTAINAHAB000000000000", "method": "manual" }
}Getting a Folder
GET /entities/{id}
Authorization: Bearer <token>Returns the folder with its properties and relationships. Children are represented as contains relationships:
{
"id": "01KFOLDER123ABCDEFGHJKMNPQ",
"cid": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy",
"type": "folder",
"properties": {
"label": "Pequod Crew Profiles",
"description": "Profiles of all crew members aboard the Pequod"
},
"relationships": [
{ "predicate": "collection", "peer": "01KFNR0H0Q791Y1SMZWEQ09FGV", "peer_type": "collection" },
{ "predicate": "in", "peer": "01KPARENT789ABCDEFGHJKMNPQ", "peer_type": "folder" },
{ "predicate": "contains", "peer": "01KFILE789ABCDEFGHJKMNPQRS", "peer_type": "file", "peer_label": "ahab-profile.pdf" },
{ "predicate": "contains", "peer": "01KFILE012ABCDEFGHJKMNPQRS", "peer_type": "file", "peer_label": "starbuck-profile.pdf" }
],
"ver": 3,
"created_at": "2025-01-15T10:00:00.000Z",
"ts": 1736940000000,
"edited_by": { "user_id": "01JCAPTAINAHAB000000000000", "method": "manual" }
}To list folder contents, filter the relationships array for predicate: "contains".
Expanding Relationship Details
Use ?expand=relationships:preview to get fresh data about children:
GET /entities/{id}?expand=relationships:previewThis adds peer_preview with current label, type, description, and timestamps for each relationship.
Updating a Folder
PUT /entities/{id}
Content-Type: application/json
Authorization: Bearer <token>
{
"expect_tip": "bafyreibug443cnd4endcwinwttw3c3dzmcl2ikht64xzn5qg56bix3usfy",
"properties": {
"label": "Pequod Crew Profiles - Updated",
"description": "Updated description"
},
"note": "Updated folder metadata"
}Properties are deep merged. Use properties_remove to delete specific properties.
Hierarchy Management
Folders use bidirectional relationships:
- Parent has
contains→ child - Child has
in→ parent
Adding Children to a Folder
Update the folder to add contains relationships:
PUT /entities/{folderId}
Content-Type: application/json
Authorization: Bearer <token>
{
"expect_tip": "bafyrei_folder_tip...",
"relationships_add": [
{ "predicate": "contains", "peer": "01KFILE789ABCDEFGHJKMNPQRS", "peer_type": "file" }
],
"note": "Added file to folder"
}Then update the child to add the in back-link:
PUT /entities/{childId}
Content-Type: application/json
Authorization: Bearer <token>
{
"expect_tip": "bafyrei_child_tip...",
"relationships_add": [
{ "predicate": "in", "peer": "01KFOLDER123ABCDEFGHJKMNPQ", "peer_type": "folder" }
]
}Removing Children from a Folder
Remove relationships from both entities:
# Remove from folder
PUT /entities/{folderId}
{
"expect_tip": "bafyrei...",
"relationships_remove": [
{ "predicate": "contains", "peer": "01KFILE789ABCDEFGHJKMNPQRS" }
]
}
# Remove from child
PUT /entities/{childId}
{
"expect_tip": "bafyrei...",
"relationships_remove": [
{ "predicate": "in", "peer": "01KFOLDER123ABCDEFGHJKMNPQ" }
]
}Efficient Batch Hierarchy Setup
When creating many children for a folder, use the batch endpoint for efficiency:
Step 1: Create children with upward relationships
POST /entities/batch
Content-Type: application/json
Authorization: Bearer <token>
{
"default_collection": "01KFNR0H0Q791Y1SMZWEQ09FGV",
"entities": [
{
"type": "file",
"properties": { "label": "Chapter 1" },
"relationships": [
{ "predicate": "in", "peer": "01KFOLDER123...", "peer_type": "folder" }
]
},
{
"type": "file",
"properties": { "label": "Chapter 2" },
"relationships": [
{ "predicate": "in", "peer": "01KFOLDER123...", "peer_type": "folder" }
]
}
]
}Step 2: Get folder's current tip
GET /entities/{folderId}/tipStep 3: Update folder with all contains relationships
PUT /entities/{folderId}
{
"expect_tip": "bafyrei...",
"relationships_add": [
{ "predicate": "contains", "peer": "01KCHILD1...", "peer_type": "file" },
{ "predicate": "contains", "peer": "01KCHILD2...", "peer_type": "file" }
]
}For 100 children: 3 requests total (1 batch + 1 tip + 1 update) instead of 102 individual requests.
Moving Items Between Folders
To move an item from one folder to another:
Step 1: Update the item's in relationship
PUT /entities/{itemId}
{
"expect_tip": "bafyrei...",
"relationships_add": [
{ "predicate": "in", "peer": "01KNEW_FOLDER...", "peer_type": "folder" }
],
"relationships_remove": [
{ "predicate": "in", "peer": "01KOLD_FOLDER..." }
]
}Step 2: Update the old folder
PUT /entities/{oldFolderId}
{
"expect_tip": "bafyrei...",
"relationships_remove": [
{ "predicate": "contains", "peer": "01KITEM..." }
]
}Step 3: Update the new folder
PUT /entities/{newFolderId}
{
"expect_tip": "bafyrei...",
"relationships_add": [
{ "predicate": "contains", "peer": "01KITEM...", "peer_type": "file" }
]
}Browsing Folder Trees
Use the tree endpoint to get a hierarchical view:
GET /entities/{folderId}/tree?depth=2&predicates=containsQuery parameters:
depth- Max tree depth (1-4, default 2)predicates- Comma-separated predicates to follow (e.g., "contains")collection- Constrain to entities in this collectionlimit- Max nodes to return (default 100)
Response:
{
"root": {
"id": "01KFOLDER...",
"type": "folder",
"label": "Documents",
"children": [
{
"id": "01KFILE1...",
"type": "file",
"label": "Report.pdf",
"predicate": "contains"
},
{
"id": "01KSUBFOLDER...",
"type": "folder",
"label": "Images",
"predicate": "contains",
"children": [...]
}
]
},
"stats": { "total_nodes": 15, "max_depth_reached": 2 }
}Nesting
Folders can be nested to any depth. The hierarchy is maintained through bidirectional relationship pairs:
- Child has
in→ parent - Parent has
contains→ child
Maintaining both directions ensures traversal works in either direction and enables efficient tree queries.
Collections as Root Containers
Collections can act as root folders. Add contains relationships from a collection to files/folders to make them top-level items:
PUT /entities/{collectionId}
{
"expect_tip": "bafyrei...",
"relationships_add": [
{ "predicate": "contains", "peer": "01KFOLDER...", "peer_type": "folder" }
]
}For permissions, entities should also have a collection relationship (set via the collection field when creating).