Repository navigation
agents subman skill references server api.zh CN
English | 简体中文
完整端点说明见 Server API,机器契约见 OpenAPI,尚未实现的资源接口见 API 路线图。sing-box-vps 的调用流程见 集成指南。
这是面向站点所有者及可信后端脚本的 API,与浏览器 UI 运行在同一个 Cloudflare
Worker,通过同一个 WorkspaceCoordinator Durable Object 写入工作区 Gist。
除 GET /api/health 外,所有公开端点都要求:
Authorization: Bearer <SUBMAN_API_TOKEN>SUBMAN_API_TOKEN 和 GitHub Token 相互独立。它是共享的全权限凭证,没有 scope
或单客户端撤销能力。脚本只持有该 API Token,通过 TLS 发送,不放入 URL 或日志,
并支持轮换;GITHUB_TOKEN 保留在 Worker 内。
PUT /api/nodes/by-key/:externalKey稳定 key 对应一个节点,保存为以下节点标签:
external:<externalKey>
可选
vps-1-vless、hostname-vless-reality 或 server-id-protocol-port 等稳定值。
- 标签上限 128 字节,扣除 9 字节
external:前缀,新增或修改的 key 最多为 119 UTF-8 字节。 - 为自动标签预留一个槽位,最多传 63 个去重后的普通标签。
- key 仅 URL 编码一次。字面百分号序列是 key 内容,服务端不会二次解码。 去除首尾空白后按大小写精确匹配。
- 调用方不得提交保留的
external:标签。 - 幂等性只保证资源身份;重复成功调用可更新
updatedAt、推进工作区 revision。 不支持Idempotency-Key。 - PUT 替换所有可写字段。省略
tags、enabled、source使用创建默认值, 不保留旧值。PATCH 的tags替换完整列表,可能移除 key 标签;托管节点使用 by-key PUT。 - 删除节点后,再次 by-key PUT 可以创建一个新 ID;旧 ID 的 tombstone 不会被复活。
curl --fail-with-body -sS -X PUT "https://subman.example.com/api/nodes/by-key/vps-1-vless" \
-H "Authorization: Bearer ${SUBMAN_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name":"vps-1 vless","type":"vless","raw":"vless://...","enabled":true,"tags":["sing-box-vps"]}'vless://... 只是占位符,真实调用需替换为有效节点链接。
{
"name": "vps-1 vless",
"type": "vless",
"raw": "vless://...",
"enabled": true,
"tags": ["sing-box-vps", "auto"],
"source": "single"
}name、type、raw 必填。重名自动添加时间戳后缀,例如
HK 2026-05-26 06:32;首尾去空白后相同的 raw URI 返回
409 duplicate_node_raw。enabled 默认 true,source 默认 single,
tags 默认空数组。标签可以是字符串或 { "id": "...", "label": "..." }。
允许的 type:
vless, vmess, trojan, ss, ssr, hysteria2, tuic, anytls, other
| 方法和路径 | 用途 |
|---|---|
GET /api/health |
检查 Worker secret 是否配置 |
GET /api/nodes |
列出节点 |
POST /api/nodes |
创建节点,拒绝重复 raw URI |
GET /api/nodes/:id |
获取单个节点 |
PATCH /api/nodes/:id |
部分更新,处理重名并拒绝 raw 冲突 |
DELETE /api/nodes/:id |
删除节点并清理聚合规则 nodeIds
|
PUT /api/nodes/by-key/:externalKey |
按稳定外部 key 创建或更新 |
只有这些 health 和 node 路由属于公开集成契约。
/api/workspaces/:workspaceId/mutations 使用另一套凭证及 envelope,是内部浏览器
传输协议,不提供第三方兼容保证。订阅、聚合、发布和导出尚无公开 REST 端点。
- Node API 写入返回
2xx,表示协调器已提交并回读验证远端 Workspace。 浏览器的peer-owned、retry-scheduled等完成状态不适用于该 API。 - 成功节点响应的 JSON
workspace.revision、X-SubMan-Revision和强 ETag"subman-revision-12"反映版本。 - 写入可发送上次 ETag 作为
If-Match。过期值返回412 precondition_failed、state-conflict和当前 revision;重新读取后决定是否重施意图。 - 不带
If-Match的并发写入仍可能返回409 revision_conflict。 - GET 只是观察快照。无工作区时可创建 bootstrap Gist;V1/bootstrap revision 为 0。
API 由 Worker 凭证独立发现目标,没有工作区选择器。多个或无效候选返回脱敏的
502 gist_read_failed。使用 ETag 前核对workspace.gistId,版本号不标识 Gist。 - Health 始终 HTTP 200,必须检查
ok。它只检查 secret 存在,不验证 GitHub 权限、发现结果或协调器 binding。 - 节点写入不修改已有发布输出。审查相关规则后在浏览器重新发布。
错误格式为 { "error": { "code", "message", "disposition" } }。按 code
和 disposition 分支,不解析 message。可重试 GitHub 故障可能附带有界的
gateway 元数据和 Retry-After,不返回原始上游响应体。
- GET:传输或
retryable-upstream故障可使用有界退避。 - by-key PUT:只有确认尚未提交的可重试故障才可重试。不确定响应后先 GET 列表, 查找精确 external 标签;盲目重放可再次推进 revision。没有 GET-by-key 端点。
- PATCH:结果不确定时先重读节点与版本。
- POST:不盲目重试未知结果,以免重复创建。
- DELETE:未知结果后先重读;重复删除可能返回
entity_deleted或entity_not_found。
retryable-upstream 不证明写入尚未提交;PATCH 超时、回读验证或提交索引失败可能
发生在写入成功之后。先核实结果,再按安全重试时间决定是否重新提交。
领域限制使用 400 invalid_mutation,超过 9 MiB 的请求体使用
413 payload_too_large;500 workspace_size_limit 表示 operator-repair。
每次写入都带版本,协调器防止丢失更新,但 Gist 仍适合低频写入。
首次写入可原地迁移 V1 并创建不可变 subman.v1.backup.json;遇到
migration_backup_conflict 应调查备份,不覆盖它。CORS 不向任意浏览器来源开放,
也不是鉴权边界。duplicate_node_raw 表示 URI 已存在或资产清单不一致,先检查既有
节点。可信脚本宿主被入侵时轮换 API Token。
SubMan Wiki
| English | 简体中文 |
|---|---|
| User guide | 使用指南 |
| Development | 开发指南 |
| Server API | 接口文档 |
| Operations | 运维与恢复 |
| Migration | 旧版迁移 |
| sing-box export | sing-box 导出 |
| CI/CD | CI/CD |
| Roadmap | 路线图 |
| Changelog | 变更记录 |