Folder Management
Overview
Spuree is an agent-friendly cloud storage. Projects contain folders (nestable) and files at any level. This skill manages folders — they can be nested to any depth within a project.
Use this skill when an agent needs to:
- Create, rename, move, or delete folders in a project
- Browse a folder's contents (sub-folders, entities, files)
- List assets or files within a folder
- Get download URLs for files in bulk
API terminology: In the API, folders are called
sessions (
). All API fields use
,
, etc. This document uses
folder for clarity.
Authentication
Authorization: Bearer $SPUREE_ACCESS_TOKEN
Or use an API key:
X-API-Key: $SPUREE_API_KEY
See the authentication skill for obtaining tokens and managing API keys.
Base URL
https://data.spuree.com/api/v1/sessions
Data Model
Folder Hierarchy
Project (creative_project) ← see project-management skill
├── Folder (session)
│ ├── Sub-folder (session)
│ │ └── ...
│ ├── Entity (asset) character, motion, prop, environment, visdev, pose
│ │ └── Files
│ └── Files
├── Entity (asset)
│ └── Files
└── Files
Session Types
| This document calls it | Description |
|---|
| Project | Top-level container (managed via project-management skill) |
| Folder | Organizes content hierarchically |
| Entity / Asset | Asset container (character, motion, prop, etc.) |
| Animation | Animation session |
Entity Types
Entities represent assets and have one of these types:
Endpoints
POST /v1/sessions
Create a new folder.
Description: Creates a folder under a parent (project, folder, animation, or entity). The name must be compatible with Windows file system naming rules.
Request Body:
| Field | Type | Required | Description |
|---|
| string | Yes | Folder name (Windows filesystem-compatible) |
| string | Yes | Parent ObjectId (project, folder, animation, or entity) |
| string | No | Folder description |
| string[] | No | Tags for the folder |
Response:
json
{
"messageCode": "success",
"sessionId": "64a7b8c9d1e2f3a4b5c6d7e8"
}
Status Codes:
| Code | Description |
|---|
| 200 | Folder created |
| 400 | Invalid name, invalid parent ID, parent type not allowed, or entity nesting limit exceeded |
| 401 | Invalid or expired token |
| 403 | Not authorized to create in this parent |
| 404 | Parent not found or deleted |
| 409 | Folder name already exists in the parent |
| 500 | Internal server error |
Nesting rules:
- Allowed parents: , , ,
- Entity sessions allow only 1 level of sub-folders. Creating a folder under a folder that is already inside an entity is rejected.
Example:
bash
curl -X POST "https://data.spuree.com/api/v1/sessions" \
-H "Authorization: Bearer $SPUREE_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Characters",
"parentSessionId": "64a7b8c9d1e2f3a4b5c6d7e8",
"description": "All character assets",
"tags": ["characters"]
}'
PATCH /v1/sessions/{sessionId}
Update a folder (rename, move, or edit tags).
Description: Updates folder metadata. Supports renaming, moving to a different parent, and updating description/tags. Only folders (
) can be updated via this endpoint.
Path Parameters:
| Parameter | Type | Description |
|---|
| string | Folder ObjectId |
Request Body (all fields optional, at least one required):
| Field | Type | Description |
|---|
| string | New folder name |
| string | New description |
| string[] | New tags |
| string | Move to a new parent (project, folder, animation, or entity) |
Response:
json
{
"messageCode": "success",
"sessionId": "64a7b8c9d1e2f3a4b5c6d7e8"
}
Status Codes:
| Code | Description |
|---|
| 200 | Folder updated |
| 400 | No fields provided, circular reference, or nesting limit exceeded |
| 401 | Invalid or expired token |
| 403 | Not authorized, or session is not a folder |
| 404 | Folder not found, or target parent not found |
| 409 | Name conflict in target parent |
| 500 | Internal server error |
Move notes:
- Moving a folder automatically inherits workspace and project IDs from the new parent.
- Circular references are detected and rejected (cannot move a folder into its own descendant).
Examples:
bash
# Rename a folder
curl -X PATCH "https://data.spuree.com/api/v1/sessions/64a7b8c9d1e2f3a4b5c6d7e8" \
-H "Authorization: Bearer $SPUREE_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Renamed Folder"}'
# Move a folder to a different parent
curl -X PATCH "https://data.spuree.com/api/v1/sessions/64a7b8c9d1e2f3a4b5c6d7e8" \
-H "Authorization: Bearer $SPUREE_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"parentSessionId": "64a7b8c9d1e2f3a4b5c6d7f0"}'
DELETE /v1/sessions/{sessionId}
Delete a folder (soft delete).
Description: Soft-deletes a folder by setting its status to "deleted". Only folders (
) can be deleted via this endpoint.
Path Parameters:
| Parameter | Type | Description |
|---|
| string | Folder ObjectId |
Response:
json
{
"messageCode": "success",
"sessionId": "64a7b8c9d1e2f3a4b5c6d7e8"
}
Status Codes:
| Code | Description |
|---|
| 200 | Folder soft-deleted |
| 400 | Invalid folder ID format |
| 401 | Invalid or expired token |
| 403 | Not authorized, or session is not a folder |
| 404 | Folder not found or already deleted |
| 500 | Internal server error |
Example:
bash
curl -X DELETE "https://data.spuree.com/api/v1/sessions/64a7b8c9d1e2f3a4b5c6d7e8" \
-H "Authorization: Bearer $SPUREE_ACCESS_TOKEN"
GET /v1/sessions/{sessionId}/children
Browse a folder's immediate contents.
Description: Returns the direct children of a folder: sub-folders, entities (assets), and files. Same response format as
GET /v1/projects/{projectId}/children
.
Path Parameters:
| Parameter | Type | Description |
|---|
| string | Folder ObjectId |
Query Parameters:
| Parameter | Type | Default | Description |
|---|
| integer | 100 | Results per page (max: 500) |
| integer | 0 | Number of items to skip |
Response:
json
{
"sessions": [
{
"id": "64a7b8c9d1e2f3a4b5c6d7e8",
"name": "Sub-folder",
"sessionType": "session",
"status": "active",
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-01-15T10:00:00Z"
}
],
"entities": [
{
"id": "64a7b8c9d1e2f3a4b5c6d7e9",
"name": "Hero Character",
"entityType": "character",
"description": "Main character",
"entityPreview": {
"presignedUrl": "https://s3.amazonaws.com/...",
"key": "previews/hero_low.jpg",
"fileFormat": "jpg"
},
"highResEntityPreview": {
"presignedUrl": "https://s3.amazonaws.com/...",
"key": "previews/hero_high.jpg",
"fileFormat": "jpg"
}
}
],
"files": [
{
"id": "64a7b8c9d1e2f3a4b5c6d7ea",
"fileName": "reference_sheet",
"fileFormat": "png",
"key": "works_abc/sess_def/file_ghi",
"sourceCharacter": null,
"presignedUrl": "https://s3.amazonaws.com/...",
"annotationMetaData": {}
}
]
}
Children Types:
| Array | Contains | Description |
|---|
| Folders | Sub-folders — navigate deeper with this same endpoint |
| Assets | Entity sessions with preview images |
| Files | Files with presigned download URLs |
Entity Fields:
| Field | Type | Description |
|---|
| string | Entity ObjectId |
| string | Entity name |
| string | , , , , , |
| string? | Entity description |
| object? | Low-res preview (, , ) |
| object? | High-res preview |
File Fields:
| Field | Type | Description |
|---|
| string | File ObjectId |
| string | File name (without extension) |
| string | File extension (lowercase) |
| string | S3 object key |
| string? | Associated character name |
| string | S3 presigned download URL |
| object | Metadata (fps, frameCount, durationSeconds, ueAssetType, etc.) |
Status Codes:
| Code | Description |
|---|
| 200 | Children returned |
| 400 | Invalid folder ID format |
| 401 | Invalid or expired token |
| 403 | Not authorized to access this folder |
| 404 | Folder not found or deleted |
| 500 | Internal server error |
Example:
bash
curl "https://data.spuree.com/api/v1/sessions/64a7b8c9d1e2f3a4b5c6d7e8/children?limit=50" \
-H "Authorization: Bearer $SPUREE_ACCESS_TOKEN"
GET /v1/sessions/{sessionId}/assets
Get assets (entities) in a folder.
Description: Returns entity sessions and their associated files for a given folder.
Path Parameters:
| Parameter | Type | Description |
|---|
| string | Folder ObjectId |
Query Parameters:
| Parameter | Type | Default | Description |
|---|
| string | | Comma-separated: |
| integer | 100 | Results per page (max: 500) |
| integer | 0 | Number of items to skip |
Response:
json
{
"assets": [
{
"id": "64a7b8c9d1e2f3a4b5c6d7e9",
"name": "Hero Character",
"entityType": "character",
"description": "Main character",
"entityPreview": { "presignedUrl": "...", "key": "...", "fileFormat": "jpg" },
"highResEntityPreview": { "presignedUrl": "...", "key": "...", "fileFormat": "jpg" }
}
],
"files": [
{
"id": "64a7b8c9d1e2f3a4b5c6d7ea",
"fileName": "hero_model",
"fileFormat": "fbx",
"key": "works_abc/sess_def/file_ghi",
"sourceCharacter": "Hero",
"presignedUrl": "https://s3.amazonaws.com/...",
"annotationMetaData": { "fileSize": "1048576" }
}
]
}
Status Codes:
| Code | Description |
|---|
| 200 | Assets and files returned |
| 400 | Invalid folder ID format |
| 401 | Invalid or expired token |
| 403 | Not authorized |
| 404 | Folder not found |
| 500 | Internal server error |
Example:
bash
curl "https://data.spuree.com/api/v1/sessions/64a7b8c9d1e2f3a4b5c6d7e8/assets" \
-H "Authorization: Bearer $SPUREE_ACCESS_TOKEN"
GET /v1/sessions/{sessionId}/files
Get files in a folder.
Description: Returns files associated with a folder. By default, flattens results to include files from sub-folders via entity session linkage.
Path Parameters:
| Parameter | Type | Description |
|---|
| string | Folder ObjectId |
Query Parameters:
| Parameter | Type | Default | Description |
|---|
| boolean | | : files by (includes sub-folders). : files by direct only |
| integer | 100 | Results per page (max: 500) |
| integer | 0 | Number of items to skip |
Response:
json
{
"files": [
{
"id": "64a7b8c9d1e2f3a4b5c6d7ea",
"fileName": "hero_walk",
"fileFormat": "fbx",
"key": "works_abc/sess_def/file_ghi",
"sourceCharacter": "Hero",
"presignedUrl": "https://s3.amazonaws.com/...",
"annotationMetaData": {
"fps": 30,
"frameCount": 300,
"durationSeconds": 10.0,
"fileSize": "1048576"
}
}
]
}
Status Codes:
| Code | Description |
|---|
| 200 | Files returned |
| 400 | Invalid folder ID format |
| 401 | Invalid or expired token |
| 403 | Not authorized |
| 404 | Folder not found |
| 500 | Internal server error |
Example:
bash
# Get all files (flattened, including sub-folders)
curl "https://data.spuree.com/api/v1/sessions/64a7b8c9d1e2f3a4b5c6d7e8/files" \
-H "Authorization: Bearer $SPUREE_ACCESS_TOKEN"
# Get only direct files in this folder
curl "https://data.spuree.com/api/v1/sessions/64a7b8c9d1e2f3a4b5c6d7e8/files?flatten=false" \
-H "Authorization: Bearer $SPUREE_ACCESS_TOKEN"
POST /v1/sessions/files/download/urls
Get download URLs for multiple files in bulk.
Description: Generates presigned S3 download URLs for a batch of files. Validates access permissions for each file.
Request Body:
| Field | Type | Required | Description |
|---|
| string[] | Yes | File ObjectIds to download |
| integer | No | URL expiry in seconds (60–86400, default: 3600) |
| boolean | No | Include file metadata (default: ) |
Response:
json
{
"downloads": [
{
"fileId": "64a7b8c9d1e2f3a4b5c6d7ea",
"fileName": "hero_walk.fbx",
"fileSize": 1048576,
"format": "fbx",
"downloadUrl": "https://s3.amazonaws.com/...",
"expiresAt": "2024-01-15T11:00:00Z",
"sessionId": "64a7b8c9d1e2f3a4b5c6d7e8",
"entitySessionId": "64a7b8c9d1e2f3a4b5c6d7e9",
"metadata": {
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-01-15T10:00:00Z"
}
}
],
"totalFiles": 1,
"totalSize": 1048576,
"unauthorizedFiles": [],
"notFoundFiles": []
}
Status Codes:
| Code | Description |
|---|
| 200 | Download URLs generated |
| 400 | Invalid input |
| 401 | Invalid or expired token |
| 403 | Not authorized for some files (listed in ) |
| 503 | AWS credentials error |
| 500 | Internal server error |
Example:
bash
curl -X POST "https://data.spuree.com/api/v1/sessions/files/download/urls" \
-H "Authorization: Bearer $SPUREE_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"fileIds": ["64a7b8c9d1e2f3a4b5c6d7ea", "64a7b8c9d1e2f3a4b5c6d7eb"],
"expiresIn": 7200,
"includeMetadata": true
}'
Common Patterns
Navigate a Project's Folder Structure
-
Get project children (via project-management skill):
GET /v1/projects/{projectId}/children → { sessions, entities, files }
-
Navigate into a folder:
GET /v1/sessions/{folderId}/children → { sessions, entities, files }
-
Repeat to go deeper into sub-folders.
Create a Folder Structure
bash
# Create a top-level folder in a project
POST /v1/sessions { name: "Characters", parentSessionId: "{projectId}" }
→ { sessionId: "folder1" }
# Create a sub-folder
POST /v1/sessions { name: "Heroes", parentSessionId: "folder1" }
→ { sessionId: "folder2" }
Download All Files in a Folder
-
List files in the folder:
GET /v1/sessions/{folderId}/files?flatten=true → { files: [...] }
-
Get download URLs in bulk:
POST /v1/sessions/files/download/urls { fileIds: [...] }
→ { downloads: [{ downloadUrl, ... }] }
-
Download each file using its
.
Agent Workflow: Asset Discovery
- Browse project → find the folder containing assets
- Get assets →
GET /v1/sessions/{folderId}/assets
- Get files → for each asset, list its files
- Download → batch download with
POST /v1/sessions/files/download/urls
Studio URLs
After creating or finding resources, you can give the user a clickable link to view them in the browser:
| Resource | URL Pattern |
|---|
| Project | https://studio.spuree.com/projects/{projectId}
|
| Folder (top-level) | https://studio.spuree.com/projects/{projectId}/folders/{folderId}
|
| Folder (nested) | https://studio.spuree.com/projects/{projectId}/folders/{parentId}/{childId}
|
| File | https://studio.spuree.com/file/{fileId}
|
Folders support up to 5 levels of nesting. Each level appends another ID segment:
.../folders/{level1}/{level2}/{level3}/...
Error Handling
| Error | Cause | Resolution |
|---|
| 400 (invalid name) | Name contains invalid filesystem characters | Use Windows-compatible names |
| 400 (nesting limit) | Trying to nest more than 1 level under an entity | Restructure: entities allow only 1 sub-folder level |
| 400 (circular ref) | Moving a folder into its own descendant | Choose a different target parent |
| 401 (unauthorized) | Expired or invalid JWT | Refresh token via authentication skill |
| 403 (not a folder) | Trying to update/delete a non-folder session | Only can be modified here |
| 404 (not found) | Folder doesn't exist or was deleted | Verify the folder ID |
| 409 (name conflict) | Folder name already exists in the parent | Use a different name |