REST API Reference
PuppyOne provides a complete REST API covering content management, agent configuration, data sync, collaborative editing, and more.
Basic information
Base URL
Production:
https://api.puppyone.ai/api/v1Self-hosted:
http://localhost:9090/api/v1Authentication
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_xxxCommon parameters
Some list endpoints support these query parameters:
| Parameter | Type | Description |
|---|---|---|
project_id | string | Project ID, required for most endpoints |
org_id | string | Organization ID |
1. Authentication
Get public config
GET /auth/configReturns public Supabase configuration, URL and anon key, for client-side Realtime connections.
Log in
POST /auth/loginRequest body:
{
"email": "[email protected]",
"password": "your-password"
}Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "v1.xxx",
"expires_in": 3600
}Refresh token
POST /auth/refreshRequest body:
{
"refresh_token": "v1.xxx"
}Initialize user
POST /auth/initializeAn 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 organizationInvitations
POST /organizations/{org_id}/invite # Send invitation
GET /organizations/{org_id}/invitations # Show pending invitations
POST /organizations/invitations/{token}/accept # Accept invitation3. 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}/dashboardReturns 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 memberSeed default content
POST /projects/{project_id}/seedCreates default sample content for the project.
4. Content nodes
Content Nodes are PuppyOne's core data unit. Four types are supported: folder, json, markdown, and file.
List nodes
GET /nodes/?project_id={project_id}&parent_id={parent_id}| Parameter | Type | Required | Description |
|---|---|---|---|
project_id | string | Yes | Project ID |
parent_id | string | No | Parent node ID. If omitted, returns the root |
Get a single node
GET /nodes/{node_id}Response:
{
"id": "node_xxx",
"name": "config.json",
"type": "json",
"content": { "key": "value" },
"parent_id": "node_parent",
"project_id": "proj_xxx",
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
}Get a node by path
GET /nodes/by-path?project_id={project_id}&path=/folder/file.jsonGet a node by ID path
GET /nodes/by-id-path/?project_id={project_id}&id_path=id1/id2/id3Batch get nodes
GET /nodes/batch?ids=node_1,node_2,node_3Create folder
POST /nodes/folderRequest body:
{
"name": "reports",
"project_id": "proj_xxx",
"parent_id": "node_parent"
}Create JSON node
POST /nodes/jsonRequest body:
{
"name": "config.json",
"project_id": "proj_xxx",
"parent_id": "node_parent",
"content": { "key": "value", "nested": { "a": 1 } }
}Create Markdown node
POST /nodes/markdownRequest body:
{
"name": "README.md",
"project_id": "proj_xxx",
"parent_id": "node_parent",
"content": "# Hello\n\nThis is a markdown file."
}Batch create nodes
POST /nodes/bulk-createRequest body:
{
"project_id": "proj_xxx",
"parent_id": "node_parent",
"nodes": [
{ "name": "a.json", "type": "json", "content": {} },
{ "name": "b.md", "type": "markdown", "content": "# B" }
]
}Upload file
POST /nodes/uploadReturns a presigned upload URL, and the client uploads the file directly to S3.
Update node
PUT /nodes/{node_id}Request body:
{
"name": "new-name.json",
"content": { "updated": true }
}Move node
POST /nodes/{node_id}/moveRequest body:
{
"new_parent_id": "node_target_folder"
}Delete node
DELETE /nodes/{node_id}Soft delete only. The node is moved into the .trash folder.
Get download URL
GET /nodes/{node_id}/downloadReturns a presigned download URL for file-type nodes.
Version history
GET /nodes/{node_id}/versions # List versions
GET /nodes/{node_id}/versions/{version} # Get version content
POST /nodes/{node_id}/rollback/{version} # Roll back to a version
GET /nodes/{node_id}/diff/{v1}/{v2} # Compare two versionsVersion 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"
}
]Folder snapshots
GET /nodes/{folder_id}/snapshots # Snapshot history
POST /nodes/{folder_id}/rollback-snapshot/{snapshot_id} # Roll back to a snapshotAudit logs
GET /nodes/{node_id}/audit-logsReturns the full operation history for a node, who did what and when.
Response:
[
{
"action": "update",
"actor_type": "user",
"actor_id": "user_xxx",
"node_id": "node_xxx",
"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| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | No | JSON Pointer path, defaults to / |
Create data
POST /tables/{table_id}/dataRequest body:
{
"path": "/products",
"data": {
"id": "SKU-003",
"name": "New Widget",
"price": 129.99
}
}Update data
PUT /tables/{table_id}/dataRequest body:
{
"path": "/products/0/price",
"value": 89.99
}Delete data
DELETE /tables/{table_id}/data?path=/products/06. Connection management
Connections are PuppyOne's unified integration abstraction, covering agents, MCP endpoints, sandbox endpoints, sync connections, and more.
List connections
GET /connections/?project_id={project_id}Get connection
GET /connections/{connection_id}Update connection
PATCH /connections/{connection_id}Delete connection
DELETE /connections/{connection_id}Regenerate access key
POST /connections/{connection_id}/regenerate-key7. Data sync
Project sync status
GET /sync/status?project_id={project_id}List available connectors
GET /sync/connectorsReturns a list of all supported sync connector specs.
List sync jobs
GET /sync/syncs?project_id={project_id}Create sync
POST /sync/bootstrapRequest 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 syncSync run history
GET /sync/syncs/{sync_id}/runs # List run records
GET /sync/runs/{run_id} # Run detailsFolder 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 completedSync 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 bulkBash 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 bulkExecution history
GET /agent-config/{agent_id}/executions9. Agent chat
SSE streaming chat
POST /agentsStream 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 history10. MCP endpoints
List MCP endpoints
GET /mcp-endpoints?project_id={project_id}Create MCP endpoint
POST /mcp-endpointsRequest 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-keyMCP 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 keyMCP proxy forwarding
ANY /mcp/proxy # MCP server proxy
ANY /mcp/proxy/{path} # MCP server proxy subpath11. Sandbox endpoints
List sandbox endpoints
GET /sandbox-endpoints?project_id={project_id}Create sandbox endpoint
POST /sandbox-endpointsRequest 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-keyExecute command
POST /sandbox-endpoints/{endpoint_id}/execRequest body:
{
"command": "jq '.products | length' data.json"
}Response:
{
"stdout": "42",
"stderr": "",
"exit_code": 0
}12. Collaboration
PuppyOne provides a full collaborative editing workflow, including Checkout and Commit, version history, and snapshot rollback.
Checkout
POST /collab/checkoutRequest body:
{
"node_ids": ["node_1", "node_2"],
"project_id": "proj_xxx"
}Commit
POST /collab/commitRequest body:
{
"mutations": [
{
"node_id": "node_1",
"content": { "updated": true },
"message": "Update config"
}
],
"project_id": "proj_xxx"
}Version management
GET /collab/versions/{node_id} # Version history
GET /collab/versions/{node_id}/{version} # Get version content
POST /collab/rollback/{node_id}/{version} # Roll back to version
GET /collab/diff/{node_id}/{v1}/{v2} # Compare versionsFolder snapshots
GET /collab/snapshots/{folder_id} # List snapshots
POST /collab/rollback-snapshot/{folder_id}/{snapshot_id} # Roll back to snapshot13. 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/searchCreates a search tool with a vector index asynchronously.
Get search index status
GET /tools/{tool_id}/search-indexGet, update, or delete a tool
GET /tools/{tool_id}
PUT /tools/{tool_id}
DELETE /tools/{tool_id}14. Ingestion
Submit file ingestion
POST /ingest/submit/fileUpload PDFs, DOCX files, images, and more, then automatically run ETL into Markdown or JSON.
Submit URL or SaaS ingestion
POST /ingest/submit/saasPull 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 checkETL 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 rule15. 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 # DisconnectSupported {provider} values:
| Provider | Description |
|---|---|
notion | Notion workspace |
github | GitHub repository |
gmail | Gmail inbox |
google-drive | Google Drive files |
google-docs | Google Docs documents |
google-sheets | Google Sheets spreadsheets |
google-calendar | Google Calendar |
linear | Linear project management |
airtable | Airtable 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/callbackOther endpoints
Database connections
POST /db-connector/connections # Create DB connection
GET /db-connector/connections # List connections
DELETE /db-connector/connections/{connection_id} # Delete connection
GET /db-connector/connections/{id}/tables # List database tables
GET /db-connector/connections/{id}/tables/{table}/preview # Preview table data
POST /db-connector/connections/{id}/save # Save as content nodePublic publishing
POST /publishes/ # Create publish
GET /publishes/ # List publishes
PATCH /publishes/{publish_id} # Update publish
DELETE /publishes/{publish_id} # Delete publishPublic access, no auth required:
GET /p/{publish_key}Usage analytics
GET /analytics/access-timeseries # Access time series
GET /analytics/access-summary # Access summaryUser 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 onboardingWorkspace
POST /workspace/create # Create workspace
POST /workspace/{agent_id}/complete # Complete agent workspace
GET /workspace/{agent_id}/status # Workspace statusError codes
| Error code | HTTP status | Description |
|---|---|---|
UNAUTHORIZED | 401 | Invalid or missing token |
FORBIDDEN | 403 | Insufficient permissions |
NOT_FOUND | 404 | Resource not found |
VALIDATION_ERROR | 422 | Invalid request parameters |
RATE_LIMITED | 429 | Too many requests |
INTERNAL_ERROR | 500 | Internal server error |
Code examples
cURL: create a JSON Content Node
curl -X POST "https://api.puppyone.ai/api/v1/nodes/json" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "products.json",
"project_id": "proj_xxx",
"content": {
"products": [
{ "id": "SKU-001", "name": "Widget", "price": 59.99 }
]
}
}'Python: query Content Nodes
import requests
API_BASE = "https://api.puppyone.ai/api/v1"
TOKEN = "<your-token>"
headers = {"Authorization": f"Bearer {TOKEN}"}
resp = requests.get(
f"{API_BASE}/nodes/",
headers=headers,
params={"project_id": "proj_xxx"}
).json()
for node in resp["data"]["nodes"]:
print(f"{node['name']} ({node['type']})")JavaScript: get version history
const API_BASE = "https://api.puppyone.ai/api/v1";
async function getVersionHistory(token, nodeId) {
const response = await fetch(
`${API_BASE}/nodes/${nodeId}/versions`,
{
headers: { "Authorization": `Bearer ${token}` }
}
);
return response.json();
}