English
Reference
REST API Reference

REST API Reference

PuppyOne provides a complete REST API covering content management, agent configuration, data sync, and more.


Basic information

Base URL

Production:

https://api.puppyone.ai/api/v1

Self-hosted:

http://localhost:9090/api/v1

Authentication

All API requests must include authentication headers. Two authentication methods are supported:

JWT token, for user authentication:

Authorization: Bearer <access_token>

Access key, for machine or agent authentication:

Authorization: Bearer cli_xxx

Common parameters

Some list endpoints support these query parameters:

ParameterTypeDescription
project_idstringProject ID, required for most endpoints
org_idstringOrganization ID

1. Authentication

Get public config

GET /auth/config

Returns public Supabase configuration, URL and anon key, for client-side Realtime connections.

Log in

POST /auth/login

Request body:

{
  "email": "[email protected]",
  "password": "your-password"
}

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "v1.xxx",
  "expires_in": 3600
}

Refresh token

POST /auth/refresh

Request body:

{
  "refresh_token": "v1.xxx"
}

Initialize user

POST /auth/initialize

An idempotent operation that creates the user's profile and default organization. Call this after the first login.


2. Organizations

List organizations

GET /organizations/

Returns all organizations the current user belongs to.

Create organization

POST /organizations/

Request body:

{
  "name": "My Team",
  "description": "Team description"
}

Get organization details

GET /organizations/{org_id}

Update organization

PUT /organizations/{org_id}

Delete organization

DELETE /organizations/{org_id}

Member management

GET    /organizations/{org_id}/members                          # List members
PUT    /organizations/{org_id}/members/{user_id}/role           # Update role
DELETE /organizations/{org_id}/members/{user_id}                # Remove member
POST   /organizations/{org_id}/leave                            # Leave organization

Invitations

POST /organizations/{org_id}/invite                             # Send invitation
GET  /organizations/{org_id}/invitations                        # Show pending invitations
POST /organizations/invitations/{token}/accept                  # Accept invitation

3. Projects

List projects

GET /projects/?org_id={org_id}

Create project

POST /projects/

Request body:

{
  "name": "Product Knowledge Base",
  "description": "Stores product-related data",
  "org_id": "org_xxx"
}

Get project details

GET /projects/{project_id}

Update project

PUT /projects/{project_id}

Delete project

DELETE /projects/{project_id}

Project dashboard

GET /projects/{project_id}/dashboard

Returns aggregated project state, including node counts, connection status, and sync progress.

Project members

GET    /projects/{project_id}/members                           # List members
POST   /projects/{project_id}/members                           # Add member
PUT    /projects/{project_id}/members/{user_id}/role            # Update role
DELETE /projects/{project_id}/members/{user_id}                 # Remove member

Seed default content

POST /projects/{project_id}/seed

Creates default sample content for the project.


4. Content

Content is PuppyOne's core data layer. All operations use path-based addressing under the /content/{project_id}/ prefix. Three content types are supported: json, markdown, and file.

All responses are wrapped in ApiResponse:

{"success": true, "data": {...}, "message": "..."}

List directory

GET /content/{project_id}/ls?path={path}
ParameterTypeRequiredDescription
pathstringNoDirectory path. Empty or omitted returns the root

Read file

GET /content/{project_id}/cat?path={path}

Returns the file content. JSON nodes return content, Markdown nodes return content_text.

File metadata

GET /content/{project_id}/stat?path={path}

Returns metadata including type, name, content_hash, mime_type, and children_count.

Recursive tree

GET /content/{project_id}/tree?path={path}&max_depth=-1
ParameterTypeRequiredDescription
pathstringNoRoot path for the tree
max_depthintegerNoMaximum depth. -1 for unlimited (default)

List trash

GET /content/{project_id}/trash

Returns all items in the trash bin.

Write file

POST /content/{project_id}/write

Request body:

{
  "path": "reports/weekly.json",
  "content": { "title": "Weekly Report", "status": "draft" },
  "node_type": "json",
  "message": "Create weekly report"
}
FieldTypeRequiredDescription
pathstringYesFile path
contentanyYesFile content (object for JSON, string for Markdown)
node_typestringYesjson, markdown, or file
messagestringNoCommit message

Create directory

POST /content/{project_id}/mkdir

Request body:

{
  "path": "reports/2025"
}

Move / rename

POST /content/{project_id}/mv

Request body:

{
  "old_path": "reports/weekly.json",
  "new_path": "archive/weekly-old.json",
  "message": "Archive old report"
}

Delete

POST /content/{project_id}/rm

Request body:

{
  "path": "reports/weekly.json",
  "permanent": false
}

When permanent is false (default), the file is moved to trash. Set true to delete permanently.

Restore from trash

POST /content/{project_id}/restore

Request body:

{
  "trash_path": ".trash/weekly.json",
  "original_path": "reports/weekly.json"
}

Bulk write

POST /content/{project_id}/bulk-write

Request body:

{
  "files": [
    { "path": "config/a.json", "content": { "key": "value" }, "node_type": "json" },
    { "path": "docs/readme.md", "content": "# Hello", "node_type": "markdown" }
  ],
  "message": "Initial setup"
}

Version history

GET /content/{project_id}/versions?path={path}&limit=50&since_version=0
ParameterTypeRequiredDescription
pathstringYesFile path
limitintegerNoMax versions to return (default 50)
since_versionintegerNoReturn versions after this version number

Version list response:

[
  {
    "version": 3,
    "actor_type": "user",
    "actor_id": "user_xxx",
    "created_at": "2025-01-03T00:00:00Z",
    "message": "Updated config"
  },
  {
    "version": 2,
    "actor_type": "agent",
    "actor_id": "agent_xxx",
    "created_at": "2025-01-02T00:00:00Z"
  }
]

Version content

GET /content/{project_id}/version-content?path={path}&version={version}

Returns the content of a file at a specific version.

Diff

GET /content/{project_id}/diff?v1={v1}&v2={v2}

Compare two versions of the project.

Rollback

POST /content/{project_id}/rollback

Request body:

{
  "target_version": 5
}

Rolls the project back to the specified version.

Audit logs

GET /nodes/{path}/audit-logs

Returns the full operation history for a node, who did what and when.

Response:

[
  {
    "action": "update",
    "actor_type": "user",
    "actor_id": "user_xxx",
    "path": "reports/weekly.json",
    "timestamp": "2025-01-01T12:00:00Z",
    "details": {}
  }
]

5. Tables

Table APIs are a supplemental operation layer for structured JSON data. They use JSON Pointer paths to locate and modify data, but the primary data model in PuppyOne is still the Content Node.

List tables

GET /tables/?org_id={org_id}

Get table

GET /tables/{table_id}

Create table

POST /tables/

Update table

PUT /tables/{table_id}

Delete table

DELETE /tables/{table_id}

Get data

GET /tables/{table_id}/data?path=/products
ParameterTypeRequiredDescription
pathstringNoJSON Pointer path, defaults to /

Create data

POST /tables/{table_id}/data

Request body:

{
  "path": "/products",
  "data": {
    "id": "SKU-003",
    "name": "New Widget",
    "price": 129.99
  }
}

Update data

PUT /tables/{table_id}/data

Request body:

{
  "path": "/products/0/price",
  "value": 89.99
}

Delete data

DELETE /tables/{table_id}/data?path=/products/0

6. Connection management

Connections are PuppyOne's unified integration abstraction, covering agents, MCP endpoints, sandbox endpoints, sync connections, and more.

List connections

GET /access/?project_id={project_id}

Get connection

GET /access/{id}

Update connection

PATCH /access/{id}

Delete connection

DELETE /access/{id}

Regenerate access key

POST /access/{id}/regenerate-key

7. Data sync

Project sync status

GET /sync/status?project_id={project_id}

List available connectors

GET /sync/connectors

Returns a list of all supported sync connector specs.

List sync jobs

GET /sync/syncs?project_id={project_id}

Create sync

POST /sync/bootstrap

Request body:

{
  "project_id": "proj_xxx",
  "provider": "notion",
  "config": {
    "database_id": "xxx"
  }
}

Sync operations

POST   /sync/syncs/{sync_id}/refresh                           # Manual refresh
POST   /sync/syncs/{sync_id}/pause                             # Pause sync
POST   /sync/syncs/{sync_id}/resume                            # Resume sync
PATCH  /sync/syncs/{sync_id}/trigger                           # Update trigger mode
DELETE /sync/syncs/{sync_id}                                   # Delete sync

Sync run history

GET /sync/syncs/{sync_id}/runs                                 # List run records
GET /sync/runs/{run_id}                                        # Run details

Folder push and pull, for CLI sync

POST /sync/syncs/{sync_id}/push-file                           # Push local file
GET  /sync/syncs/{sync_id}/pull-files                          # Pull cloud files
POST /sync/syncs/{sync_id}/ack-pull                            # Confirm pull completed

Sync changelog

GET /sync/changelog?project_id={project_id}

8. Agent configuration

List agents

GET /agent-config/?project_id={project_id}

Get agent

GET /agent-config/{agent_id}

Get default agent

GET /agent-config/default?project_id={project_id}

Create agent

POST /agent-config/

Request body:

{
  "name": "Support Assistant",
  "project_id": "proj_xxx",
  "system_prompt": "You are a professional support assistant...",
  "model": "gpt-4o"
}

Update agent

PUT /agent-config/{agent_id}

Delete agent

DELETE /agent-config/{agent_id}

Access control

POST   /agent-config/{agent_id}/accesses                       # Add node access
PUT    /agent-config/{agent_id}/accesses/{access_id}           # Update access
DELETE /agent-config/{agent_id}/accesses/{access_id}           # Remove access
PUT    /agent-config/{agent_id}/accesses                       # Sync accesses in bulk

Bash tools

POST   /agent-config/{agent_id}/bash                           # Add Bash tool
PUT    /agent-config/{agent_id}/bash/{bash_id}                 # Update Bash tool
DELETE /agent-config/{agent_id}/bash/{bash_id}                 # Remove Bash tool
PUT    /agent-config/{agent_id}/bash                           # Sync Bash tools in bulk

Execution history

GET /agent-config/{agent_id}/executions

9. Agent chat

SSE streaming chat

POST /agents

Stream a conversation with an agent over Server-Sent Events, SSE.

Request body:

{
  "agent_id": "agent_xxx",
  "message": "Check the latest product data for me",
  "session_id": "session_xxx"
}

SSE event stream:

data: {"type": "text", "content": "Checking now..."}
data: {"type": "tool_call", "name": "query_data", "arguments": {...}}
data: {"type": "tool_result", "content": {...}}
data: {"type": "text", "content": "Here are the results..."}
data: {"type": "done"}

Chat session management

POST   /chat/sessions                                          # Create session
GET    /chat/sessions                                          # List sessions
GET    /chat/sessions/{session_id}                             # Get session
PATCH  /chat/sessions/{session_id}                             # Update session
DELETE /chat/sessions/{session_id}                             # Delete session
GET    /chat/sessions/{session_id}/messages                    # Get message history

10. MCP endpoints

List MCP endpoints

GET /mcp-endpoints?project_id={project_id}

Create MCP endpoint

POST /mcp-endpoints

Request body:

{
  "name": "Product Data MCP",
  "project_id": "proj_xxx",
  "node_id": "node_xxx"
}

Get MCP endpoint

GET /mcp-endpoints/{endpoint_id}

Get MCP endpoint by node

GET /mcp-endpoints/by-node/{node_id}

Update MCP endpoint

PUT /mcp-endpoints/{endpoint_id}

Delete MCP endpoint

DELETE /mcp-endpoints/{endpoint_id}

Regenerate API key

POST /mcp-endpoints/{endpoint_id}/regenerate-key

MCP tool bindings

GET    /mcp/agents/{agent_id}/tools                            # List bound tools
POST   /mcp/agents/{agent_id}/tools                            # Bind tool
PUT    /mcp/agents/{agent_id}/tools/{tool_id}                  # Update binding
DELETE /mcp/agents/{agent_id}/tools/{tool_id}                  # Unbind tool
GET    /mcp/agents/{agent_id}/status                           # MCP status
POST   /mcp/agents/{agent_id}/regenerate-key                   # Regenerate MCP key

MCP proxy forwarding

ANY /mcp/proxy                                                 # MCP server proxy
ANY /mcp/proxy/{path}                                          # MCP server proxy subpath

11. Sandbox endpoints

List sandbox endpoints

GET /sandbox-endpoints?project_id={project_id}

Create sandbox endpoint

POST /sandbox-endpoints

Request body:

{
  "name": "Code Sandbox",
  "project_id": "proj_xxx",
  "node_id": "node_xxx"
}

Get sandbox endpoint

GET /sandbox-endpoints/{endpoint_id}

Get sandbox endpoint by node

GET /sandbox-endpoints/by-node/{node_id}

Update sandbox endpoint

PUT /sandbox-endpoints/{endpoint_id}

Delete sandbox endpoint

DELETE /sandbox-endpoints/{endpoint_id}

Regenerate access key

POST /sandbox-endpoints/{endpoint_id}/regenerate-key

Execute command

POST /sandbox-endpoints/{endpoint_id}/exec

Request body:

{
  "command": "jq '.products | length' data.json"
}

Response:

{
  "stdout": "42",
  "stderr": "",
  "exit_code": 0
}

12. Tools

List tools

GET /tools/?org_id={org_id}

List tools by node

GET /tools/by-node/{node_id}

List tools by project

GET /tools/by-project/{project_id}

Create tool

POST /tools/

Request body:

{
  "name": "query_products",
  "node_id": "node_xxx",
  "type": "query",
  "config": {}
}

Create search tool

POST /tools/search

Creates a search tool with a vector index asynchronously.

Get search index status

GET /tools/{tool_id}/search-index

Get, update, or delete a tool

GET    /tools/{tool_id}
PUT    /tools/{tool_id}
DELETE /tools/{tool_id}

13. Ingestion

Submit file ingestion

POST /ingest/submit/file

Upload PDFs, DOCX files, images, and more, then automatically run ETL into Markdown or JSON.

Submit URL or SaaS ingestion

POST /ingest/submit/saas

Pull data from a URL or SaaS platform.

Task management

GET    /ingest/tasks/{task_id}                                 # Get task status
POST   /ingest/tasks/batch                                     # Get task status in bulk
DELETE /ingest/tasks/{task_id}                                 # Cancel task
GET    /ingest/health                                          # Ingestion service health check

ETL rules

GET    /ingest/rules                                           # List ETL rules
POST   /ingest/rules                                           # Create ETL rule
GET    /ingest/rules/{rule_id}                                 # Get rule details
DELETE /ingest/rules/{rule_id}                                 # Delete rule

14. OAuth

PuppyOne supports OAuth integrations for multiple platforms. Each platform follows the same endpoint pattern:

GET    /oauth/{provider}/authorize                             # Get authorization URL
POST   /oauth/{provider}/callback                              # Handle callback
GET    /oauth/{provider}/status                                # Check connection status
DELETE /oauth/{provider}/disconnect                            # Disconnect

Supported {provider} values:

ProviderDescription
notionNotion workspace
githubGitHub repository
gmailGmail inbox
google-driveGoogle Drive files
google-docsGoogle Docs documents
google-sheetsGoogle Sheets spreadsheets
google-calendarGoogle Calendar
linearLinear project management
airtableAirtable bases

Example, start Notion OAuth:

curl "https://api.puppyone.ai/api/v1/oauth/notion/authorize?project_id=proj_xxx" \
  -H "Authorization: Bearer <token>"

Generic browser callback:

GET /oauth/callback

Other endpoints

Database connections

POST   /db-connector/access                                    # Create DB access
GET    /db-connector/access                                    # List access points
DELETE /db-connector/access/{id}                    # Delete access point
GET    /db-connector/access/{id}/tables                        # List database tables
GET    /db-connector/access/{id}/tables/{table}/preview        # Preview table data
POST   /db-connector/access/{id}/save                          # Save as content node

Public publishing

POST   /publishes/                                             # Create publish
GET    /publishes/                                             # List publishes
PATCH  /publishes/{publish_id}                                 # Update publish
DELETE /publishes/{publish_id}                                 # Delete publish

Public access, no auth required:

GET /p/{publish_key}

Usage analytics

GET /analytics/access-timeseries                               # Access time series
GET /analytics/access-summary                                  # Access summary

User profile

GET  /profile/me                                               # Get current user info
GET  /profile/onboarding/status                                # Onboarding status
POST /profile/onboarding/complete                              # Complete onboarding
POST /profile/onboarding/reset                                 # Reset onboarding

Workspace

POST /workspace/create                                         # Create workspace
POST /workspace/{agent_id}/complete                            # Complete agent workspace
GET  /workspace/{agent_id}/status                              # Workspace status

Error codes

Error codeHTTP statusDescription
UNAUTHORIZED401Invalid or missing token
FORBIDDEN403Insufficient permissions
NOT_FOUND404Resource not found
VALIDATION_ERROR422Invalid request parameters
RATE_LIMITED429Too many requests
INTERNAL_ERROR500Internal server error

Code examples

cURL: write a JSON file

curl -X POST "https://api.puppyone.ai/api/v1/content/proj_xxx/write" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "path": "products.json",
    "node_type": "json",
    "content": {
      "products": [
        { "id": "SKU-001", "name": "Widget", "price": 59.99 }
      ]
    },
    "message": "Add product catalog"
  }'

Python: list and read content

import requests
 
API_BASE = "https://api.puppyone.ai/api/v1"
PROJECT_ID = "proj_xxx"
TOKEN = "<your-token>"
 
headers = {"Authorization": f"Bearer {TOKEN}"}
 
resp = requests.get(
    f"{API_BASE}/content/{PROJECT_ID}/ls",
    headers=headers,
).json()
 
for entry in resp["data"]:
    print(f"{entry['name']} ({entry['type']})")

JavaScript: get version history

const API_BASE = "https://api.puppyone.ai/api/v1";
const PROJECT_ID = "proj_xxx";
 
async function getVersionHistory(token, filePath) {
  const params = new URLSearchParams({ path: filePath });
  const response = await fetch(
    `${API_BASE}/content/${PROJECT_ID}/versions?${params}`,
    {
      headers: { "Authorization": `Bearer ${token}` }
    }
  );
  return response.json();
}