Arke
Build

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:preview

This 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}/tip

Step 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=contains

Query parameters:

  • depth - Max tree depth (1-4, default 2)
  • predicates - Comma-separated predicates to follow (e.g., "contains")
  • collection - Constrain to entities in this collection
  • limit - 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).

On this page