Skip to content

Latest commit

 

History

History
719 lines (556 loc) · 18.5 KB

File metadata and controls

719 lines (556 loc) · 18.5 KB

🛠️ 管理 API

注意:以下内容适用于有一定技术能力的用户,否则请跳过此页面!!!

本文档说明如何直接调用 Metapi 管理后台的 /api/* 接口,用脚本完成站点与账号管理。

返回文档维护页

返回文档首页


适用范围

这组接口适合以下场景:

  • 初始化新实例,批量导入站点和账号
  • 用 Shell / Python / CI 脚本维护现有管理数据
  • 在外部系统里接入 Metapi 后台能力,而不是手工点页面

Important

本页介绍的是 管理 API,不是下游客户端调用的 /v1/* 代理接口。

  • 管理 API 使用 AUTH_TOKEN
  • 代理接口使用 PROXY_TOKEN

认证方式

所有受保护的管理接口都需要携带:

Authorization: Bearer <AUTH_TOKEN>

其中:

  • AUTH_TOKEN 就是你启动 Metapi 时配置的管理员令牌
  • 如果你后来在「设置」里修改过管理员令牌,脚本里也要同步改成新值
  • 管理端如果启用了 ADMIN_IP_ALLOWLIST,脚本调用方的来源 IP 也必须命中白名单

管理 API 不需要额外先调用“登录接口”;脚本直接带 AUTH_TOKEN 即可。

推荐先准备两个环境变量:

export METAPI_ADMIN_BASE_URL="http://127.0.0.1:4000"
# 或者
# export METAPI_ADMIN_BASE_URL="https://your-domain.com"
export METAPI_AUTH_TOKEN="your-admin-token"

之后所有请求都可以复用:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/sites" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}"

通用约定

项目 说明
接口前缀 管理接口统一在 /api/*
请求体 默认使用 application/json
认证方式 Authorization: Bearer <AUTH_TOKEN>
成功判定 除了看 HTTP 状态码,也要看响应体里的 success / error / message
业务失败返回 有些接口会返回 200,但响应体里是 success: false
常见错误码 400 参数错误、401/403 认证失败、409 资源冲突、429 触发限流

Tip

对脚本来说,最稳妥的做法是:

  1. 先检查 HTTP 状态码
  2. 再检查返回 JSON 里的 successerrormessage
  3. 不要只靠 200 判断调用成功

常用脚本流程

脚本化添加一个新站点并绑定账号,通常按下面顺序:

  1. POST /api/sites/detect 自动识别平台
  2. 如命中官方预设,记下返回的 initializationPresetId
  3. POST /api/sites 创建站点
  4. POST /api/accounts/verify-token 验证凭证
  5. POST /api/accounts 保存账号

如果你要自动化的是 Codex / Claude / Gemini CLI / Antigravity 这类 provider 授权,则改看本文后面的 OAuth 接口,不要强行走普通账号导入。

最小流程示例:

# 1. 自动识别站点类型
curl -sS "${METAPI_ADMIN_BASE_URL}/api/sites/detect" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com"
  }'

# 2. 创建站点
curl -sS "${METAPI_ADMIN_BASE_URL}/api/sites" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My New API",
    "url": "https://api.example.com",
    "platform": "new-api"
  }'

# 3. 验证 API Key 或 Session Token
curl -sS "${METAPI_ADMIN_BASE_URL}/api/accounts/verify-token" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": 1,
    "accessToken": "sk-or-session-token",
    "credentialMode": "apikey"
  }'

# 4. 保存账号
curl -sS "${METAPI_ADMIN_BASE_URL}/api/accounts" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": 1,
    "accessToken": "sk-or-session-token",
    "credentialMode": "apikey"
  }'

站点接口

1. 获取站点列表

GET /api/sites

返回当前全部站点。响应除了站点自身字段,还会带上聚合出来的 totalBalancesubscriptionSummary

示例:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/sites" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}"

示例响应:

[
  {
    "id": 1,
    "name": "My New API",
    "url": "https://api.example.com",
    "platform": "new-api",
    "status": "active",
    "useSystemProxy": false,
    "totalBalance": 42.5,
    "subscriptionSummary": null
  }
]

2. 自动识别站点类型

POST /api/sites/detect

用于在真正创建站点前,先根据 URL 探测平台类型;如果命中官方预设,还会顺带返回 initializationPresetId

请求体:

字段 类型 必填 说明
url string 待识别的站点地址。通用平台通常传根地址;如果你想命中官方预设,则直接传预设对应的完整地址

示例:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/sites/detect" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com"
  }'

成功响应:

{
  "url": "https://api.example.com",
  "platform": "new-api"
}

命中预设时,响应可能类似:

{
  "url": "https://coding.dashscope.aliyuncs.com/v1",
  "platform": "openai",
  "initializationPresetId": "codingplan-openai"
}

失败响应:

{
  "error": "Could not detect platform"
}

3. 创建站点

POST /api/sites

请求体字段:

字段 类型 必填 说明
name string 站点名称
url string 站点地址。通用平台通常用根地址;官方预设可直接保留完整官方路径
platform string 平台类型;留空时服务端会再次尝试自动识别
initializationPresetId string 官方预设 ID;用于保留预设语义、初始化建议和后续跳转
proxyUrl string | null 站点专用代理地址,支持 http(s) / socks
useSystemProxy boolean 是否使用全局 SYSTEM_PROXY_URL
customHeaders string | null 自定义请求头,注意这里传的是 JSON 字符串
externalCheckinUrl string | null 外部签到地址,需为 http(s)
status string activedisabled
isPinned boolean 是否置顶
sortOrder number 排序值,非负整数
globalWeight number 站点全局权重,必须为正数
apiEndpoints array 仅用于 API 请求的数据面地址池;不替代主站点 URL

示例:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/sites" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Proxy Site",
    "url": "https://proxy-site.example.com",
    "platform": "new-api",
    "proxyUrl": "socks5://127.0.0.1:1080",
    "useSystemProxy": true,
    "customHeaders": "{\"cf-access-client-id\":\"site-client-id\",\"x-site-scope\":\"internal\"}",
    "externalCheckinUrl": "https://checkin.example.com/welfare",
    "globalWeight": 1.5
  }'

成功响应示例:

{
  "id": 1,
  "name": "Proxy Site",
  "url": "https://proxy-site.example.com",
  "platform": "new-api",
  "proxyUrl": "socks5://127.0.0.1:1080",
  "useSystemProxy": true,
  "customHeaders": "{\"cf-access-client-id\":\"site-client-id\",\"x-site-scope\":\"internal\"}",
  "externalCheckinUrl": "https://checkin.example.com/welfare",
  "status": "active",
  "globalWeight": 1.5
}

常见失败:

  • 409:同一个 (platform, url) 已存在
  • 400proxyUrlexternalCheckinUrlcustomHeadersglobalWeight 等字段格式不合法

Tip

customHeaders 不是对象,而是 JSON 字符串;并且 value 必须是字符串。

4. 使用官方预设创建站点

如果你前一步 detect 已经拿到了 initializationPresetId,推荐在创建时显式带回去:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/sites" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Aliyun CodingPlan",
    "url": "https://coding.dashscope.aliyuncs.com/v1",
    "platform": "openai",
    "initializationPresetId": "codingplan-openai"
  }'

这样响应里也会保留该预设信息,便于脚本按预设类型做后续分流。

账号接口

1. 获取账号列表

GET /api/accounts

返回账号快照对象,而不是裸数组。响应里包含:

  • generatedAt:快照生成时间
  • accounts:当前全部账号,以及关联站点、凭证模式、能力信息、今日花费、运行健康状态等聚合字段
  • sites:前端常用的站点列表快照

示例:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/accounts" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}"

示例响应:

{
  "generatedAt": "2026-04-09T06:00:00.000Z",
  "accounts": [
    {
      "id": 1,
      "siteId": 1,
      "username": "alice",
      "status": "active",
      "credentialMode": "apikey",
      "capabilities": {
        "canCheckin": false,
        "canRefreshBalance": false,
        "proxyOnly": true
      },
      "site": {
        "id": 1,
        "name": "My New API",
        "url": "https://api.example.com",
        "platform": "new-api"
      }
    }
  ],
  "sites": [
    {
      "id": 1,
      "name": "My New API",
      "url": "https://api.example.com",
      "platform": "new-api"
    }
  ]
}

2. 验证凭证

POST /api/accounts/verify-token

建议在真正保存账号前先调用一次。这样脚本可以在入库前拿到更明确的错误信息。

请求体字段:

字段 类型 必填 说明
siteId number 目标站点 ID
accessToken string Session Token / Session Cookie / API Key
platformUserId number 某些 new-api / anyrouter 站点需要手动传
credentialMode string auto / session / apikey,脚本里推荐显式传

验证 API Key

curl -sS "${METAPI_ADMIN_BASE_URL}/api/accounts/verify-token" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": 1,
    "accessToken": "sk-fast-verify",
    "credentialMode": "apikey"
  }'

成功响应:

{
  "success": true,
  "tokenType": "apikey",
  "modelCount": 2,
  "models": ["gpt-5-mini", "gpt-4o-mini"]
}

验证 Session Token

curl -sS "${METAPI_ADMIN_BASE_URL}/api/accounts/verify-token" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": 1,
    "accessToken": "session=xxxx",
    "credentialMode": "session"
  }'

成功响应:

{
  "success": true,
  "tokenType": "session",
  "userInfo": {
    "username": "alice"
  },
  "balance": 12.34,
  "apiToken": "sk-generated-by-upstream"
}

Tip

new-api / anyrouter 一类站点,如果返回 needsUserId: true,说明脚本里要补上 platformUserId 再重试。

3. 保存账号

POST /api/accounts

请求体字段:

字段 类型 必填 说明
siteId number 目标站点 ID
accessToken string 输入凭证;即使是 API Key 模式,也先放这里
username string 用户名;Session 模式下通常可由服务端自动识别
apiToken string 可显式指定要保存的 API Key;留空时服务端会自动推断
platformUserId number 平台用户 ID,New API 系站点常用
checkinEnabled boolean Session 模式下是否开启签到
credentialMode string auto / session / apikey
refreshToken string sub2api 会话可附带刷新令牌
tokenExpiresAt number | string sub2api 会话过期时间戳
skipModelFetch boolean true 时可跳过即时模型拉取

保存 API Key 账号

curl -sS "${METAPI_ADMIN_BASE_URL}/api/accounts" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": 1,
    "accessToken": "sk-proxy-only",
    "credentialMode": "apikey"
  }'

成功响应示例:

{
  "id": 1,
  "siteId": 1,
  "tokenType": "apikey",
  "credentialMode": "apikey",
  "capabilities": {
    "canCheckin": false,
    "canRefreshBalance": false,
    "proxyOnly": true
  },
  "modelCount": 1,
  "apiTokenFound": true,
  "queued": true,
  "jobId": "task_xxx",
  "message": "已添加为 API Key 账号,后台正在同步模型和路由信息。"
}

保存 Session 账号

curl -sS "${METAPI_ADMIN_BASE_URL}/api/accounts" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "siteId": 1,
    "accessToken": "session=xxxx",
    "credentialMode": "session",
    "platformUserId": 1001,
    "checkinEnabled": true
  }'

常见失败:

  • 400 + requiresVerification: true:凭证还没有通过验证,建议先调用 /api/accounts/verify-token
  • 400siteId 不存在、Token 为空、凭证类型与 credentialMode 不匹配

Tip

对纯脚本导入场景,建议始终显式传 credentialMode,不要依赖 auto 推断。

4. 重新绑定 Session Token

POST /api/accounts/:id/rebind-session

用于账号 Session 过期后,脚本直接把新 Session Token 重新写回账号。

请求体字段:

字段 类型 必填 说明
accessToken string 新的 Session Token
platformUserId number 覆盖或补充平台用户 ID
refreshToken string sub2api 会话可附带
tokenExpiresAt number | string sub2api 会话过期时间戳

示例:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/accounts/1/rebind-session" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "accessToken": "session=new-token",
    "platformUserId": 1001
  }'

成功响应示例:

{
  "success": true,
  "tokenType": "session",
  "credentialMode": "session",
  "apiTokenFound": true
}

OAuth 接口

如果你要自动化的是 Codex / Claude / Gemini CLI / Antigravity 这类 provider 授权,请使用下面这组接口。

1. 获取可用 provider

GET /api/oauth/providers

示例:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/oauth/providers" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}"

示例响应:

{
  "providers": [
    {
      "provider": "codex",
      "label": "Codex",
      "platform": "codex",
      "enabled": true,
      "loginType": "oauth",
      "requiresProjectId": false,
      "supportsDirectAccountRouting": true,
      "supportsCloudValidation": true,
      "supportsNativeProxy": true
    }
  ]
}

2. 启动 OAuth 授权

POST /api/oauth/providers/:provider/start

请求体字段:

字段 类型 必填 说明
projectId string 某些 provider 可选传入的项目 ID,例如 Gemini CLI
proxyUrl string | null 本次 OAuth 流程使用的显式代理;传 null 可清空继承代理

示例:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/oauth/providers/codex/start" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{}'

成功响应:

{
  "provider": "codex",
  "state": "oauth-state-123",
  "authorizationUrl": "https://auth.example.com/authorize?...",
  "instructions": {
    "redirectUri": "http://localhost:1455/auth/callback",
    "callbackPort": 1455,
    "callbackPath": "/auth/callback",
    "manualCallbackDelayMs": 15000
  }
}

3. 查询 OAuth 会话状态

GET /api/oauth/sessions/:state

示例:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/oauth/sessions/oauth-state-123" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}"

典型状态包括:

  • pending
  • success
  • error

4. 手动回填 callback URL

POST /api/oauth/sessions/:state/manual-callback

当浏览器已经完成授权,但回调没有自动打到 Metapi 时,可以手动提交最终 callback URL。

curl -sS "${METAPI_ADMIN_BASE_URL}/api/oauth/sessions/oauth-state-123/manual-callback" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "callbackUrl": "http://localhost:1455/auth/callback?code=demo&state=oauth-state-123"
  }'

5. 列出已有 OAuth 连接

GET /api/oauth/connections

示例:

curl -sS "${METAPI_ADMIN_BASE_URL}/api/oauth/connections?limit=50&offset=0" \
  -H "Authorization: Bearer ${METAPI_AUTH_TOKEN}"

6. 重绑或删除 OAuth 连接

接口 作用
POST /api/oauth/connections/:accountId/rebind 为已有 OAuth 账号重新发起授权
DELETE /api/oauth/connections/:accountId 删除 OAuth 连接

常见失败返回

站点创建冲突

当同一个 (platform, url) 已存在时,会返回:

{
  "error": "A new-api site with URL https://api.example.com already exists."
}

需要补平台用户 ID

某些 new-api / anyrouter 站点会返回:

{
  "success": false,
  "needsUserId": true,
  "message": "This site requires a user ID. Please fill in your site user ID."
}

这时请在 /api/accounts/verify-token/api/accounts 里补上 platformUserId

平台用户 ID 不匹配

{
  "success": false,
  "invalidUserId": true,
  "message": "The provided user ID does not match this token. Please check your site user ID."
}

命中防护盾

{
  "success": false,
  "shieldBlocked": true,
  "message": "This site is shielded by anti-bot challenge. Create an API key on the target site and import that key."
}

这通常意味着账号密码或 Session 流程被防护页拦住了,更适合改用 API Key 模式。

验证过于频繁

POST /api/accounts/verify-token 对同一来源 IP 有速率限制。超过限制后会返回:

{
  "success": false,
  "message": "请求过于频繁,请稍后再试"
}

建议脚本在这类错误上做退避重试。

下一步

  • 上游接入 — 查看不同站点类型应该怎么填 URL、凭证和 User ID
  • OAuth 管理 — 查看浏览器授权、回调和重绑逻辑
  • 配置说明 — 查看 AUTH_TOKENADMIN_IP_ALLOWLIST、系统代理等配置项
  • 客户端接入 — 如果你要接的是 /v1/* 代理接口而不是后台管理接口,请看这里