本文档面向“要真正开始调用”的使用者,提供一套从启用、认证、资源创建到刷新校验的最短上手路径。
如果你需要完整路由与字段定义,请同时查看:
- 概览文档:
docs/external-management-api.md - OpenAPI:
docs/external-management-api.openapi.yaml
调用前需要满足:
- MiSub 实例已经正常部署
- 已在 System Settings → External Management API 中启用该功能
- 已配置至少一个 Bearer Token
对应设置示例:
{
"externalApi": {
"enabled": true,
"tokens": [
{
"name": "default",
"token": "your-strong-random-token"
}
]
}
}如果未启用,会返回:
{
"success": false,
"error": {
"code": "forbidden",
"message": "External API is disabled"
}
}如果 Token 缺失或错误,会返回:
{
"success": false,
"error": {
"code": "unauthorized",
"message": "Invalid or missing bearer token"
}
}基础路径:
https://your-domain.example/api/ext/v1
建议先在 shell 中设置两个环境变量:
export MISUB_BASE_URL='https://your-domain.example/api/ext/v1'
export MISUB_TOKEN='your-strong-random-token'后续请求统一带:
-H "Authorization: Bearer $MISUB_TOKEN"如果是 JSON 请求,再加:
-H 'Content-Type: application/json'先确认 API 已启用、Token 正确、路由可达:
curl -s \
-H "Authorization: Bearer $MISUB_TOKEN" \
"$MISUB_BASE_URL/subscriptions"成功时典型返回:
{
"success": true,
"data": [],
"meta": {
"page": 1,
"pageSize": 50,
"total": 0,
"requestId": "req_xxx"
}
}表示远程订阅源:
url必须是http://或https://- 会参与远程拉取、节点统计、流量信息提取
适合机场订阅、聚合订阅等远程地址。
表示手动节点:
url必须是单条节点协议链接- 不能是
http(s)
适合直接保存 vless://、trojan://、ss:// 等单节点。
表示订阅组:
- 通过
subscriptionIds引用远程订阅源 - 通过
manualNodeIds引用手动节点
profile 本身不直接内嵌完整资源内容,只维护引用关系。
推荐外部系统按下面顺序接入:
- 连通性测试
- 校验候选 subscription / manual node
- 创建 subscription / manual node
- 创建 profile
- 给 profile 绑定 subscriptionIds / manualNodeIds
- 需要时执行 preview / refresh
用于“先试一遍远程地址是否可拉取、可解析”。
curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com/subscription.txt",
"userAgent": "ClashMeta",
"proxy": ""
}' \
"$MISUB_BASE_URL/subscriptions/validate"适用场景:
- 外部面板保存前预检
- 用户输入远程订阅地址后即时校验
- 调试 user-agent / fetch proxy 是否影响拉取结果
curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "Airport A",
"url": "https://example.com/subscription.txt",
"enabled": true,
"group": "HK",
"tags": ["prod"],
"userAgent": "ClashMeta",
"proxy": "",
"sortIndex": 1
}' \
"$MISUB_BASE_URL/subscriptions"curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "SG-01",
"url": "trojan://password@example.com:443#SG-01"
}' \
"$MISUB_BASE_URL/manual-nodes/validate"适用场景:
- 外部表单在保存前检测节点链接是否合法
- 解析节点协议、名称、基础元信息
curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "SG-01",
"url": "trojan://password@example.com:443#SG-01",
"group": "SG",
"tags": ["manual"],
"remarks": "from external system"
}' \
"$MISUB_BASE_URL/manual-nodes"curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "Main",
"description": "default profile",
"target": "clash",
"subscriptionIds": [],
"manualNodeIds": []
}' \
"$MISUB_BASE_URL/profiles"curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"subscriptionIds": ["sub_xxx"]
}' \
"$MISUB_BASE_URL/profiles/profile_xxx/subscriptions"curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"manualNodeIds": ["node_xxx"]
}' \
"$MISUB_BASE_URL/profiles/profile_xxx/manual-nodes"curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
"$MISUB_BASE_URL/subscriptions/sub_xxx/refresh"该接口会更新并持久化:
nodeCountuserInfolastErrorlastUpdate
curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"subscriptionIds": ["sub_a", "sub_b"]
}' \
"$MISUB_BASE_URL/subscriptions/batch-refresh"适合:
- 外部后台手动触发批量同步
- 周期任务对指定机场做刷新
curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
"$MISUB_BASE_URL/profiles/profile_xxx/preview"注意:
- 这是轻量预览
- 当前不会主动拉取远程订阅内容
- 更适合做资源概览,不适合当作真实刷新结果
curl -s -X POST \
-H "Authorization: Bearer $MISUB_TOKEN" \
"$MISUB_BASE_URL/profiles/profile_xxx/refresh"适合:
- 外部系统希望“一次刷新某个 profile 关联的全部远程订阅”
- 获取聚合后的
summary.totalNodes
推荐流程:
- 远程订阅地址 →
POST /subscriptions/validate - 手动节点链接 →
POST /manual-nodes/validate - 校验通过后再调用创建接口
优点:
- 减少脏数据进入 MiSub
- 可以把错误尽早反馈给用户
推荐流程:
- 定期
GET /subscriptions/GET /manual-nodes/GET /profiles - 基于本地业务系统决定增删改
- 对远程订阅定期调用
refresh
如果外部 UI 上有“同步这个配置组”按钮,推荐直接调用:
POST /profiles/:profileId/refresh
这样外部系统不需要自己枚举其关联的 subscriptionIds。
preview:轻量聚合视图refresh:真实刷新远程订阅,并写回运行时字段
如果你要真实节点数、流量信息、失败原因,应该用 refresh。
- 删除 subscription 时,会从所有 profile 移除其 ID
- 删除 manual node 时,也会做同样处理
所以外部系统不需要再额外手工清理关联关系。
POST /profiles/:id/subscriptions:追加并去重DELETE /profiles/:id/subscriptions:移除指定 IDPOST /profiles/:id/manual-nodes:追加并去重DELETE /profiles/:id/manual-nodes:移除指定 ID
它们不是“整对象覆盖写入”。
下面是一条从 0 到 1 的最短链路:
GET /subscriptions验证 Token 与路由POST /subscriptions/validate校验远程订阅地址POST /subscriptions创建订阅源POST /profiles创建 profilePOST /profiles/:id/subscriptions绑定订阅源POST /profiles/:id/refresh获取真实刷新结果
如果你要:
- 看完整字段定义 →
docs/external-management-api.openapi.yaml - 看真实行为边界 →
docs/external-management-api.md - 看整个项目 API 边界 →
docs/api-routes.md