REST API
通过 HTTP 接口直接操作 PuppyOne 的 Content Node。
概述
如果你在构建自己的 Agent、自动化脚本或后端服务,可以直接调用 PuppyOne 的 REST API 来读写 Content Node。这种方式最灵活,适合需要把 PuppyOne 接入现有系统、工作流或服务端逻辑的场景。
基本信息
Base URL
| 环境 | Base URL |
|---|---|
| 云端 | https://api.puppyone.ai/api/v1 |
| 自部署 | http://localhost:9090/api/v1 |
认证
所有请求都需要携带认证头:
Authorization: Bearer <access_key>通常你会为 REST API 集成单独创建一个 Access Key,避免和其他 MCP / 沙盒 / 文件同步连接共用。
核心接口
PuppyOne 的主数据模型是 Content Node 树。常见场景里,你最常用的是以下几组接口。
1. 列出节点
GET /nodes?project_id={project_id}&parent_id={parent_id}适合浏览目录、列出某个文件夹下的子节点。
2. 获取节点详情
GET /nodes/{node_id}?project_id={project_id}适合读取某个 JSON / Markdown / 文件节点的详细信息。
3. 创建文件夹
POST /nodes/folder{
"project_id": "proj_xxx",
"parent_id": "node_parent",
"name": "reports"
}4. 创建 JSON 节点
POST /nodes/json{
"project_id": "proj_xxx",
"parent_id": "node_parent",
"name": "weekly-report.json",
"content": {
"title": "周报",
"summary": "本周完成了产品定价调整。"
}
}5. 创建 Markdown 节点
POST /nodes/markdown{
"project_id": "proj_xxx",
"parent_id": "node_docs",
"name": "README.md",
"content": "# 项目说明\n\n这里是文档正文。"
}6. 更新节点
PUT /nodes/{node_id}{
"name": "README.md",
"content": "# 项目说明\n\n这里是更新后的正文。"
}7. 删除节点
DELETE /nodes/{node_id}8. 上传文件
POST /nodes/upload适合 PDF、图片、附件等二进制内容。服务端会返回上传地址,客户端再把文件传到存储层。
Python 示例
import httpx
BASE_URL = "https://api.puppyone.ai/api/v1"
ACCESS_KEY = "sk_live_xxx"
PROJECT_ID = "proj_xxx"
headers = {
"Authorization": f"Bearer {ACCESS_KEY}",
"Content-Type": "application/json",
}
async def list_nodes(parent_id=None):
params = {"project_id": PROJECT_ID}
if parent_id:
params["parent_id"] = parent_id
async with httpx.AsyncClient() as client:
resp = await client.get(f"{BASE_URL}/nodes", headers=headers, params=params)
resp.raise_for_status()
return resp.json()["data"]["nodes"]
async def get_node(node_id):
async with httpx.AsyncClient() as client:
resp = await client.get(
f"{BASE_URL}/nodes/{node_id}",
headers=headers,
params={"project_id": PROJECT_ID},
)
resp.raise_for_status()
return resp.json()["data"]
async def create_json_node(parent_id, name, content):
body = {
"project_id": PROJECT_ID,
"parent_id": parent_id,
"name": name,
"content": content,
}
async with httpx.AsyncClient() as client:
resp = await client.post(f"{BASE_URL}/nodes/json", headers=headers, json=body)
resp.raise_for_status()
return resp.json()["data"]
async def update_node(node_id, content):
async with httpx.AsyncClient() as client:
resp = await client.put(
f"{BASE_URL}/nodes/{node_id}",
headers=headers,
json={"content": content},
)
resp.raise_for_status()
return resp.json()["data"]JavaScript / Node.js 示例
const BASE_URL = "https://api.puppyone.ai/api/v1";
const ACCESS_KEY = "sk_live_xxx";
const PROJECT_ID = "proj_xxx";
const headers = {
Authorization: `Bearer ${ACCESS_KEY}`,
"Content-Type": "application/json",
};
async function listNodes(parentId) {
const params = new URLSearchParams({ project_id: PROJECT_ID });
if (parentId) params.set("parent_id", parentId);
const resp = await fetch(`${BASE_URL}/nodes?${params}`, { headers });
if (!resp.ok) throw new Error(await resp.text());
const data = await resp.json();
return data.data.nodes;
}
async function getNode(nodeId) {
const params = new URLSearchParams({ project_id: PROJECT_ID });
const resp = await fetch(`${BASE_URL}/nodes/${nodeId}?${params}`, { headers });
if (!resp.ok) throw new Error(await resp.text());
const data = await resp.json();
return data.data;
}
async function createJsonNode(parentId, name, content) {
const resp = await fetch(`${BASE_URL}/nodes/json`, {
method: "POST",
headers,
body: JSON.stringify({
project_id: PROJECT_ID,
parent_id: parentId,
name,
content,
}),
});
if (!resp.ok) throw new Error(await resp.text());
const data = await resp.json();
return data.data;
}适合什么场景
- 你在做自研 Agent,需要完全控制请求、响应和重试逻辑
- 你要把 PuppyOne 接到现有后端服务或自动化流程中
- 你只需要读写数据,不需要 MCP 客户端那套接入体验
如果你更希望“开箱即用”,通常 MCP 会更省事;如果你需要更细粒度的工程控制,REST API 更合适。