English
CLI Reference
File System REST API

Content Operations (REST API)

All content operations in PuppyOne are performed through the REST API at /api/v1/content/{project_id}/.... Files and folders are identified by path (e.g., docs/readme.md), not by UUID.


Base URL and authentication

All requests use this pattern:

BASE_URL="https://api.puppyone.ai/api/v1/content/{project_id}"
TOKEN="YOUR_ACCESS_TOKEN"

Include the authorization header in every request:

Authorization: Bearer $TOKEN

Endpoint overview

EndpointMethodDescription
/{project_id}/ls?path=GETList directory
/{project_id}/cat?path=GETRead file content
/{project_id}/stat?path=GETGet file/dir metadata
/{project_id}/tree?path=&max_depth=GETFull directory tree
/{project_id}/trashGETList trash bin
/{project_id}/writePOSTWrite file
/{project_id}/mkdirPOSTCreate directory
/{project_id}/mvPOSTMove or rename
/{project_id}/rmPOSTDelete / trash
/{project_id}/restorePOSTRestore from trash
/{project_id}/bulk-writePOSTBulk write files
/{project_id}/versions?path=&limit=GETVersion history
/{project_id}/version-content?path=&version=GETContent at version
/{project_id}/diff?v1=&v2=GETCompare versions
/{project_id}/rollbackPOSTRollback to a version

Browse and read

List a directory

# List the root directory
curl "$BASE_URL/ls" \
  -H "Authorization: Bearer $TOKEN"
 
# List a specific path
curl "$BASE_URL/ls?path=docs" \
  -H "Authorization: Bearer $TOKEN"

Read file content

curl "$BASE_URL/cat?path=docs/readme.md" \
  -H "Authorization: Bearer $TOKEN"

Get file or directory metadata

curl "$BASE_URL/stat?path=docs/readme.md" \
  -H "Authorization: Bearer $TOKEN"

Browse as a tree

# Full tree from root
curl "$BASE_URL/tree" \
  -H "Authorization: Bearer $TOKEN"
 
# Subtree with depth limit
curl "$BASE_URL/tree?path=docs&max_depth=2" \
  -H "Authorization: Bearer $TOKEN"

Create and write

Create a directory

curl -X POST "$BASE_URL/mkdir" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path": "docs/guides"}'

Write a file

Write creates the file if it does not exist, or updates it if it does.

# Write a JSON file
curl -X POST "$BASE_URL/write" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "path": "config/settings.json",
    "content": {"theme": "dark", "lang": "zh"},
    "node_type": "json",
    "message": "Initial settings"
  }'
 
# Write a Markdown file
curl -X POST "$BASE_URL/write" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "path": "docs/readme.md",
    "content": "# Hello World\n\nWelcome to PuppyOne.",
    "node_type": "markdown",
    "message": "Add readme"
  }'

Bulk write

Write multiple files in a single request:

curl -X POST "$BASE_URL/bulk-write" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "files": [
      {"path": "data/products.json", "content": [{"name": "Widget"}], "node_type": "json"},
      {"path": "docs/changelog.md", "content": "# Changelog", "node_type": "markdown"}
    ],
    "message": "Seed initial data"
  }'

File management

Move or rename

curl -X POST "$BASE_URL/mv" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"old_path": "docs/draft.md", "new_path": "published/article.md"}'

Delete

# Soft delete (moves to trash)
curl -X POST "$BASE_URL/rm" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path": "docs/outdated.md", "permanent": false}'

List trash

curl "$BASE_URL/trash" \
  -H "Authorization: Bearer $TOKEN"

Restore from trash

curl -X POST "$BASE_URL/restore" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path": "docs/outdated.md"}'

Version management

Every write automatically creates a new version (Mut commit), so you can inspect history, compare changes, and roll back at any time.

View version history

curl "$BASE_URL/versions?path=docs/readme.md&limit=10" \
  -H "Authorization: Bearer $TOKEN"

Read content at a specific version

curl "$BASE_URL/version-content?path=docs/readme.md&version=3" \
  -H "Authorization: Bearer $TOKEN"

Compare two versions

curl "$BASE_URL/diff?v1=1&v2=3" \
  -H "Authorization: Bearer $TOKEN"

Roll back to a version

curl -X POST "$BASE_URL/rollback" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"target_version": 2}'

Rollback creates a new commit whose content matches the target version, so no intermediate history is lost.


Practical workflows

Scaffold a project structure

# Create directories
curl -X POST "$BASE_URL/mkdir" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path": "docs"}'
 
curl -X POST "$BASE_URL/mkdir" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path": "config"}'
 
# Write initial content
curl -X POST "$BASE_URL/write" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "path": "config/settings.json",
    "content": {"version": "1.0", "env": "production"},
    "node_type": "json",
    "message": "Initial config"
  }'

Import data from a script

# Pipe API response into PuppyOne
DATA=$(curl -s https://api.example.com/data)
curl -X POST "$BASE_URL/write" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"path\": \"imports/api-data.json\", \"content\": $DATA, \"node_type\": \"json\"}"

Compare and roll back

# Check version history
curl "$BASE_URL/versions?path=config/settings.json" \
  -H "Authorization: Bearer $TOKEN"
 
# Compare versions
curl "$BASE_URL/diff?v1=3&v2=5" \
  -H "Authorization: Bearer $TOKEN"
 
# Roll back
curl -X POST "$BASE_URL/rollback" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"target_version": 3}'