Skip to content

Sakura AI API v1 参考文档 ​

Complete API reference for Android developers. All endpoints prefixed with /api/v1.

← Documentation Index · README


1. 基础信息 ​

Base URL ​

https://ai.firefly520.top/api/v1

认证方式 ​

采用 双模认证,优先 Bearer Token,回退 Cookie:

方式Header / Cookie
Bearer Token(推荐,移动端)Authorization: Bearer <jwt_token>
Cookie(WebUI 兼容)Cookie: webui_token=<jwt_token>

JWT Token 通过 OAuth 登录流程获取,有效期 24 小时(86400 秒)。

认证级别 ​

级别要求角色说明
免认证无Setup Wizard 相关端点
auth任意已登录用户user / admin / super_admin
adminadmin 或 super_admin管理员操作
super_adminsuper_admin超级管理员操作

统一响应格式 ​

成功响应 ​

json
{
  "success": true,
  "message": "ok",
  "data": { ... }
}

分页响应 ​

json
{
  "success": true,
  "message": "ok",
  "data": {
    "items": [ ... ],
    "total": 100,
    "page": 1,
    "total_pages": 5,
    "per_page": 20
  }
}

分页参数说明:

参数类型默认值范围说明
pageint1>= 1页码
per_pageint201-100每页数量

错误响应 ​

json
{
  "success": false,
  "error": "错误描述",
  "detail": "详细信息(可选)",
  "code": "错误代码(可选)"
}

错误码说明 ​

HTTP 状态码说明
400请求参数错误
401未提供认证凭证 / 凭证无效或已过期
403权限不足(角色不满足要求)
428需要先完成 MFA 注册(全局或单用户强制 MFA)
429请求过于频繁或 MFA 连续失败后被临时锁定
404资源不存在
409资源冲突(如正在索引中)
500服务器内部错误
502上游服务错误(如 GitHub API)
504上游服务超时

限流说明 ​

端点限流策略
健康检查 GET /health10 次/秒
OAuth 授权 GET /auth/github10 次/分钟
移动端 OAuth GET /auth/github/mobile10 次/分钟
OAuth 回调 POST /auth/callback5 次/分钟
二次验证 POST /auth/2fa/verify5 次/分钟
Passkey 二次验证 POST /auth/2fa/passkey/options默认 10 次/分钟,可通过 passkeys_authentication_rate_limit 配置
Passkey 二次验证 POST /auth/2fa/passkey/verify默认 10 次/分钟,可通过 passkeys_authentication_rate_limit 配置
登出 POST /auth/logout10 次/分钟
Setup 连接测试 POST /setup/test-connection10 次/分钟
Setup 模型列表 POST /setup/ai-providers/{provider}/models10 次/分钟
配置模型列表 POST /config/ai-providers/{provider}/models10 次/分钟
Setup 完成 POST /setup/complete3 次/分钟
扫描触发 POST /scans/trigger3 次/分钟
其他端点无额外限流(按服务器默认策略)

2. 端点总览 ​

#方法路径认证级别说明
1GET/health免认证健康检查
2GET/auth/github免认证获取 GitHub OAuth 授权 URL
3GET/auth/github/mobile免认证获取移动端 GitHub OAuth 授权 URL
4POST/auth/callback免认证OAuth 回调换取 Token
5POST/auth/2fa/verify免认证二次验证并换取正式 Token
6POST/auth/logoutauth登出
7GET/auth/meauth获取当前用户信息
8GET/setup/state免认证获取 Setup 状态
9POST/setup/test-connection免认证测试连接配置
10GET/setup/ai-providers免认证获取 Setup 可用 AI 厂商
11POST/setup/ai-providers/{provider}/models免认证Setup 阶段获取模型列表
12POST/setup/save-step免认证保存单步配置
13POST/setup/complete免认证完成 Setup 全流程
14GET/dashboard/statsauth仪表盘统计
15GET/dashboard/recent-reviewsauth最近审查列表
16GET/dashboard/chart-dataauth仪表盘图表数据
17POST/dashboard/cache/refreshauth刷新仪表盘缓存
18GET/reviewsauthPR 审查列表(分页)
19GET/reviews/exportauth导出审查 CSV
20GET/reviews/{review_id}auth审查详情(含评论)
21GET/reviews/{review_id}/filesauth审查文件级统计
22GET/reviews/{review_id}/commentsauth审查评论列表
23GET/reviews/{review_id}/files/{file_path}auth特定文件评论
24GET/issuesauthIssue 分析列表(分页)
25GET/issues/statsauthIssue 统计
26GET/issues/{issue_id}authIssue 分析详情
27POST/issues/{issue_id}/reanalyzeauth重新分析 Issue
28GET/usersadmin用户列表(分页)
29POST/userssuper_admin创建用户
30GET/users/{user_id}admin用户详情
31PATCH/users/{user_id}/roleadmin修改用户角色
32PATCH/users/{user_id}/quotaadmin修改用户 PR 配额
33PATCH/users/{user_id}/issue-quotaadmin修改用户 Issue 配额
34POST/users/{user_id}/toggleadmin启用/禁用用户
35DELETE/users/{user_id}super_admin删除用户
36PATCH/users/{user_id}/infosuper_admin修改用户基本信息
37POST/users/{user_id}/reset-quotasuper_admin重置用户配额使用量
38GET/reposadmin仓库列表
39POST/repos/{repo_name}/index-docsadmin触发文档索引
40POST/repos/{repo_name}/index-codeadmin触发代码索引
41POST/repos/{repo_name}/index-issuesadmin触发 Issues 索引
42POST/repos/{repo_name}/scansuper_admin触发仓库扫描
43GET/config/ai-providerssuper_admin获取内置 AI 厂商列表
44POST/config/ai-providers/{provider}/modelssuper_admin按厂商获取模型列表
45GET/config/generalsuper_admin获取全局配置
46PATCH/config/generalsuper_admin更新全局配置
47GET/config/strategiessuper_admin获取策略配置
48PATCH/config/strategies/{section}super_admin更新策略配置 section
49GET/config/labelssuper_admin获取标签配置
50PUT/config/labelssuper_admin更新标签定义
51PATCH/config/labels/recommendationsuper_admin更新标签推荐设置
52GET/logs/reviewsauth审查日志列表(分页)
53GET/logs/reviews/{review_id}auth审查日志详情
54GET/logs/actionsadmin操作日志列表(分页)
55GET/logs/actions/{log_id}admin操作日志详情
56GET/queue/statsadmin队列统计
57GET/queue/itemsadmin队列列表(分页)
58GET/queue/items/{item_id}admin队列项详情
59POST/queue/items/{item_id}/retryadmin重试队列项
60DELETE/queue/items/{item_id}admin删除队列项
61POST/queue/purgeadmin批量清理队列
62GET/scansadmin扫描列表(分页)
63GET/scans/statsadmin扫描统计
64GET/scans/{scan_id}admin扫描详情
65POST/scans/triggersuper_admin手动触发扫描
66POST/scans/{scan_id}/retrysuper_admin重试扫描
67POST/scans/{scan_id}/cancelsuper_admin取消扫描
68GET/settingsauth获取个人设置
69PATCH/settingsauth更新个人设置
70GET/settings/aboutauth获取系统版本信息
71GET/user-configauth获取当前用户可覆盖配置
72PATCH/user-configauth更新当前用户配置覆盖
73GET/user-config/metadataauth获取用户配置元数据
74GET/billing/plansauth获取可用套餐
75POST/billing/redeemauth兑换配额码
76GET/billing/ordersauth获取订单历史
77POST/billing/ordersauth创建外部支付订单
78GET/billing/orders/{order_id}auth查询订单状态
79POST/billing/orders/{order_id}/refundsuper_admin直接退款订单
80POST/billing/admin/planssuper_admin创建套餐
81PUT/billing/admin/plans/{plan_id}super_admin编辑套餐
82DELETE/billing/admin/plans/{plan_id}super_admin删除套餐(默认软删除,可选硬删除)
83POST/billing/admin/codes/generatesuper_admin批量生成兑换码
84PUT/billing/admin/codes/{code_id}super_admin编辑兑换码
85DELETE/billing/admin/codes/{code_id}super_admin删除兑换码
86POST/billing/admin/grantsuper_admin手动为用户充值
87POST/auth/2fa/passkey/options免认证创建 API Passkey 认证 options
88POST/auth/2fa/passkey/verify免认证验证 API Passkey 认证
89GET/eventsauthSSE 事件流

3. 详细文档 ​


3.1 健康检查 ​

GET /health ​

健康检查端点,无需认证。

注意:此端点直接返回 JSON 对象,不使用统一响应包装格式(无 success/message 字段)。

认证级别:免认证

响应示例:

json
{
  "status": "ok",
  "version": "v1"
}

3.2 认证 (Auth) ​

GET /auth/github ​

获取 GitHub OAuth 授权 URL(Web 端)。返回 JSON 格式的授权链接,不会自动重定向。

认证级别:免认证

响应字段:

字段类型说明
data.authorization_urlstringGitHub OAuth 授权 URL
data.statestringCSRF 防护 state 值

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "authorization_url": "https://github.com/login/oauth/authorize?client_id=...",
    "state": "abc123..."
  }
}

GET /auth/github/mobile ​

获取移动端 GitHub OAuth 授权 URL,支持自定义 redirect_uri。

认证级别:免认证

查询参数:

参数类型必填说明
redirect_uristring否移动端回调 URI,默认使用系统配置值

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "authorization_url": "https://github.com/login/oauth/authorize?client_id=...&redirect_uri=...",
    "state": "xyz789..."
  }
}

Android 接入建议:使用 redirect_uri 参数指定 App 的 Deep Link(如 myapp://oauth/callback),用户在浏览器完成 GitHub 授权后会回调到该 URI 并携带 code 和 state 参数。

安全说明:自定义 redirect_uri 必须在服务端配置的白名单中(环境变量 MOBILE_OAUTH_ALLOWED_REDIRECT_URIS,逗号分隔)。不在白名单中的 URI 将返回 400 "不支持的回调地址"。redirect_uri 会绑定到 state 中,回调时验证一致性,防止 open redirect 攻击。


POST /auth/callback ​

移动端 OAuth 回调:用授权码换取 JWT access_token。

认证级别:免认证

限流:5 次/分钟

请求体:

字段类型必填说明
codestring是GitHub 授权码
statestring是与授权 URL 中一致的 state 值

请求示例:

json
{
  "code": "ghp_abc123",
  "state": "xyz789..."
}

响应字段:

字段类型说明
data.access_tokenstringJWT Token
data.token_typestring固定 "bearer"
data.expires_inint有效期(秒),固定 86400
data.user.substringGitHub 用户名
data.user.rolestring用户角色
data.user.user_idint系统用户 ID
data.user.github_idint | nullGitHub 用户 ID
data.user.avatar_urlstring | null头像 URL

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "token_type": "bearer",
    "expires_in": 86400,
    "user": {
      "sub": "octocat",
      "role": "user",
      "user_id": 1,
      "github_id": 12345,
      "avatar_url": "https://avatars.githubusercontent.com/u/12345?v=4"
    }
  }
}

当用户已启用 TOTP 或 Passkey,OAuth 回调不会直接签发正式 access_token,而是返回 message="mfa_required" 与临时 mfa_token:

json
{
  "success": true,
  "message": "mfa_required",
  "data": {
    "mfa_required": true,
    "mfa_token": "eyJhbGciOiJIUzI1NiIs...",
    "methods": ["totp", "recovery_code"],
    "user": {
      "sub": "octocat",
      "role": "user",
      "user_id": 1,
      "github_id": 12345,
      "avatar_url": "https://avatars.githubusercontent.com/u/12345?v=4"
    }
  }
}

客户端收到该响应后,应根据 methods 字段选择验证方式:TOTP/恢复码调用 POST /auth/2fa/verify,Passkey 调用 POST /auth/2fa/passkey/options 后再提交 POST /auth/2fa/passkey/verify 换取正式 Token。

Android 接入建议:获取 access_token 后存储到本地安全存储(如 EncryptedSharedPreferences),后续所有请求通过 Authorization: Bearer <access_token> 携带。


POST /auth/2fa/verify ​

验证 OAuth 登录后返回的临时 mfa_token 和 TOTP/恢复码,成功后签发正式 JWT access_token。

认证级别:免认证

限流:5 次/分钟

请求体:

字段类型必填说明
mfa_tokenstring是OAuth 回调返回的临时二次验证 Token
codestring是6 位 TOTP 验证码或恢复码

请求示例:

json
{
  "mfa_token": "eyJhbGciOiJIUzI1NiIs...",
  "code": "123456"
}

响应字段:同 POST /auth/callback 成功签发 Token 时的响应。

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "token_type": "bearer",
    "expires_in": 86400,
    "user": {
      "sub": "octocat",
      "role": "user",
      "user_id": 1,
      "github_id": 12345,
      "avatar_url": "https://avatars.githubusercontent.com/u/12345?v=4"
    }
  }
}

常见错误:

HTTP 状态码说明
400用户未启用二次验证、验证码/恢复码无效,或当前用户需使用 Passkey 完成验证
401mfa_token 无效或已过期
429账户因连续 MFA 验证失败被临时锁定

POST /auth/2fa/passkey/options ​

创建 API Passkey(WebAuthn)认证选项,用于移动端 Passkey 二次验证。与 TOTP/恢复码验证流程并列,客户端可根据 mfa_required 响应中的 methods 字段选择验证方式。

认证级别:免认证

请求体:

字段类型必填说明
mfa_tokenstring是OAuth 回调返回的临时二次验证 Token

响应字段:

字段类型说明
data.challenge_idstring服务端保存的 challenge ID,提交验证时需原样带回
data.public_keyobjectWebAuthn Authentication Options(PublicKeyCredentialRequestOptions JSON)
data.rp_idstringRelying Party ID
data.originstring服务端用于校验的 Origin

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "challenge_id": "base64url-challenge-id",
    "public_key": {
      "challenge": "base64url-challenge",
      "rpId": "example.com",
      "allowCredentials": [],
      "timeout": 300000,
      "userVerification": "required"
    },
    "rp_id": "example.com",
    "origin": "https://example.com"
  }
}

POST /auth/2fa/passkey/verify ​

验证 API Passkey(WebAuthn)认证结果,成功后签发正式 JWT access_token。

认证级别:免认证

请求体:

字段类型必填说明
mfa_tokenstring是OAuth 回调返回的临时二次验证 Token
challenge_idstring是POST /auth/2fa/passkey/options 返回的 challenge ID
credentialobject是WebAuthn 认证结果(navigator.credentials.get() 返回值 JSON 序列化)

响应字段:同 POST /auth/callback 成功签发 Token 时的响应。

常见错误:

HTTP 状态码说明
400Passkey 认证失败或凭证无效
401mfa_token 无效或已过期
429账户因连续 MFA 验证失败被临时锁定

POST /auth/logout ​

登出。API 模式下客户端需自行删除本地存储的 Token。

认证级别:auth

限流:10 次/分钟

响应示例:

json
{
  "success": true,
  "message": "已退出登录"
}

GET /auth/me ​

获取当前认证用户信息。

认证级别:auth

响应字段:

字段类型说明
data.substringGitHub 用户名
data.rolestring用户角色(user / admin / super_admin)
data.user_idint系统用户 ID
data.github_idint | nullGitHub 用户 ID
data.avatar_urlstring | null头像 URL

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "sub": "octocat",
    "role": "user",
    "user_id": 1,
    "github_id": 12345,
    "avatar_url": "https://avatars.githubusercontent.com/u/12345?v=4"
  }
}

3.3 Setup Wizard ​

Setup Wizard 端点仅在系统首次启动(bootstrap 模式)下可用,系统初始化完成后将返回 403 错误。

GET /setup/state ​

获取当前 Setup 状态。

认证级别:免认证

响应字段:

字段类型说明
data.statestring"completed" 或 "in_progress"
data.current_stepint当前步骤索引(-1 表示已完成)
data.missing_fieldsstring[]缺失的配置字段列表
data.field_groupsobject字段分组定义(仅 bootstrap 模式)

响应示例(已完成):

json
{
  "success": true,
  "message": "ok",
  "data": {
    "state": "completed",
    "current_step": -1,
    "missing_fields": []
  }
}

响应示例(进行中):

json
{
  "success": true,
  "message": "ok",
  "data": {
    "state": "in_progress",
    "current_step": 1,
    "missing_fields": ["GITHUB_APP_ID", "GITHUB_PRIVATE_KEY"],
    "field_groups": { "database": [...], "github": [...], "ai": [...], "rag": [...], "admin": [...] }
  }
}

POST /setup/test-connection ​

测试各类连接配置。

认证级别:免认证(需 bootstrap 模式)

限流:10 次/分钟

请求体:

字段类型必填说明
typestring是测试类型:database / redis / github / openai / telegram
database_urlstring条件数据库连接 URL(type=database)
redis_urlstring条件Redis 连接 URL(type=redis)
app_idstring条件GitHub App ID(type=github)
private_keystring条件GitHub 私钥(type=github)
providerstring否AI 厂商 ID(type=openai,默认 custom)
api_keystring条件OpenAI 兼容 API Key(type=openai)
api_basestring条件OpenAI 兼容 API Base URL(type=openai)
modelstring否用于辅助查询上下文窗口的模型名(type=openai)
bot_tokenstring条件Telegram Bot Token(type=telegram)

请求示例:

json
{
  "type": "database",
  "database_url": "mysql+aiomysql://user:pass@localhost:3306/sakura_ai"
}

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "success": true,
    "message": "数据库连接成功"
  }
}

GET /setup/ai-providers ​

获取 Setup Wizard 可选择的内置 AI 厂商列表。

认证级别:免认证(需 bootstrap 模式)

响应字段:

字段类型说明
data.providersarrayAI Provider 元数据列表,包含 id、label、base_url、default_model、是否支持模型列表和上下文窗口等信息

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "providers": [
      {
        "id": "deepseek",
        "label": "DeepSeek",
        "base_url": "https://api.deepseek.com/v1",
        "default_model": "deepseek-chat",
        "models_endpoint": "models",
        "model_detail_endpoint": "models/{model}",
        "supports_model_list": true,
        "supports_context_window": true,
        "notes": ""
      }
    ]
  }
}

POST /setup/ai-providers/{provider}/models ​

Setup 阶段按 AI 厂商获取模型列表,并尽可能提取上下文窗口信息。

认证级别:免认证(需 bootstrap 模式)

限流:10 次/分钟

路径参数:

参数类型说明
providerstringAI 厂商 ID,如 openai、deepseek、qwen、custom

请求体:

字段类型必填说明
api_keystring否API Key
api_basestring否自定义 API Base URL
modelstring否指定模型名,用于查询模型详情时辅助提取上下文窗口

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "success": true,
    "models": ["deepseek-chat", "deepseek-reasoner"],
    "context_window_k": 64,
    "message": "获取模型列表成功"
  }
}

POST /setup/save-step ​

保存单步配置。

认证级别:免认证(需 bootstrap 模式)

请求体:

字段类型必填说明
valuesobject是键值对,键为环境变量名,值为配置值

请求示例:

json
{
  "values": {
    "DATABASE_URL": "mysql+aiomysql://user:pass@localhost:3306/sakura_ai",
    "REDIS_URL": "redis://localhost:6379/0"
  }
}

响应示例:

json
{
  "success": true,
  "message": "已保存 2 项配置",
  "data": {
    "saved_count": 2
  }
}

POST /setup/complete ​

完成 Setup 全流程,触发服务重启。

认证级别:免认证(需 bootstrap 模式)

限流:3 次/分钟

请求体(所有字段均为可选,按需填写):

字段类型说明
DATABASE_URLstring数据库连接 URL
REDIS_URLstringRedis 连接 URL
GITHUB_APP_IDstringGitHub App ID
GITHUB_PRIVATE_KEYstringGitHub App 私钥
GITHUB_WEBHOOK_SECRETstringGitHub Webhook 密钥
AI_PROVIDERstringAI 厂商 ID
OPENAI_API_KEYstringOpenAI 兼容 API Key
OPENAI_API_BASEstringOpenAI 兼容 API Base URL
OPENAI_MODELstringOpenAI 兼容模型名
SUMMARY_PROVIDERstringSummary 使用的 AI 厂商 ID
TELEGRAM_BOT_TOKENstringTelegram Bot Token
APP_DOMAINstring应用域名
APP_PORTstring应用端口
LOG_LEVELstring日志级别
ADMIN_GITHUB_USERNAMEstring管理员 GitHub 用户名
ADMIN_TELEGRAM_IDstring管理员 Telegram ID
GITHUB_OAUTH_CLIENT_IDstringGitHub OAuth Client ID
GITHUB_OAUTH_CLIENT_SECRETstringGitHub OAuth Client Secret
GITHUB_OAUTH_REDIRECT_URIstringGitHub OAuth 回调地址
EMBEDDING_API_KEYstringEmbedding API Key
EMBEDDING_BASE_URLstringEmbedding Base URL
EMBEDDING_MODELstringEmbedding 模型名
EMBEDDING_PROVIDERstringEmbedding 提供商
EMBEDDING_DIMENSIONstringEmbedding 维度
RERANK_API_KEYstringRerank API Key
RERANK_BASE_URLstringRerank Base URL
RERANK_MODELstringRerank 模型名
RERANK_PROVIDERstringRerank 提供商

说明:当前 Setup 状态步骤按 database、github、ai、rag、admin 分组展示,服务端实际必填检查来自 field_groups 返回值。

响应示例:

json
{
  "success": true,
  "message": "系统初始化完成,正在重启...",
  "data": {
    "success": true,
    "message": "系统初始化完成,正在重启..."
  }
}

3.4 仪表盘 (Dashboard) ​

GET /dashboard/stats ​

获取仪表盘统计数据。按用户权限范围过滤(普通用户仅看到自己仓库的数据)。

认证级别:auth

响应字段:

字段类型说明
data.totalint审查总数
data.completedint已完成数
data.reviewingint审查中数
data.pendingint待处理数
data.failedint失败数
data.approvedint已通过数
data.changes_requestedint需修改数
data.avg_scorefloat平均评分
data.comment_countint评论总数
data.total_prompt_tokensintPrompt Token 总消耗
data.total_completion_tokensintCompletion Token 总消耗
data.total_estimated_costint预估总费用

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "total": 150,
    "completed": 130,
    "reviewing": 3,
    "pending": 5,
    "failed": 12,
    "approved": 95,
    "changes_requested": 35,
    "avg_score": 7.8,
    "comment_count": 420,
    "total_prompt_tokens": 1500000,
    "total_completion_tokens": 800000,
    "total_estimated_cost": 2300
  }
}

GET /dashboard/recent-reviews ​

获取最近 10 条审查记录。

认证级别:auth

响应字段(items 数组中每个元素):

字段类型说明
idint审查 ID
pr_idintPR ID
repo_namestring仓库名
repo_ownerstring仓库所有者
titlestringPR 标题
authorstringPR 作者
statusstring审查状态
overall_scoreint | null综合评分
decisionstring | null审查决策
strategystring | null审查策略
created_atstring创建时间(ISO 8601)
completed_atstring | null完成时间(ISO 8601)

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": [
    {
      "id": 42,
      "pr_id": 128,
      "repo_name": "my-org/my-repo",
      "repo_owner": "my-org",
      "title": "feat: add user authentication",
      "author": "octocat",
      "status": "completed",
      "overall_score": 8,
      "decision": "approve",
      "strategy": "standard",
      "created_at": "2026-04-17T10:30:00",
      "completed_at": "2026-04-17T10:31:30"
    }
  ]
}

GET /dashboard/chart-data ​

获取仪表盘图表数据,包含 4 组图表。

认证级别:auth

响应字段:

字段类型说明
data.trendobject审查趋势(最近 30 天)
data.trend.labelsstring[]日期标签(MM-DD 格式)
data.trend.completedint[]每天完成数
data.trend.failedint[]每天失败数
data.decisionsobject决策分布
data.decisions.labelsstring[]决策名称(中文)
data.decisions.countsint[]各决策数量
data.top_reposobject仓库排行 Top 10
data.top_repos.labelsstring[]仓库名
data.top_repos.countsint[]审查数量
data.tokensobjectToken 消耗趋势(最近 30 天)
data.tokens.labelsstring[]日期标签
data.tokens.tokensint[]每天消耗 Token 数

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "trend": {
      "labels": ["03-18", "03-19", "..."],
      "completed": [5, 3, "..."],
      "failed": [0, 1, "..."]
    },
    "decisions": {
      "labels": ["通过", "需修改"],
      "counts": [95, 35]
    },
    "top_repos": {
      "labels": ["my-org/my-repo", "my-org/other-repo"],
      "counts": [80, 70]
    },
    "tokens": {
      "labels": ["03-18", "03-19", "..."],
      "tokens": [50000, 30000, "..."]
    }
  }
}

POST /dashboard/cache/refresh ​

手动刷新仪表盘缓存(仅清除当前用户)。

认证级别:auth

响应示例:

json
{
  "success": true,
  "message": "缓存已刷新"
}

3.5 PR 审查 (Reviews) ​

GET /reviews ​

PR 审查列表,支持分页、搜索和过滤。

认证级别:auth

查询参数:

参数类型默认值说明
searchstring""搜索关键词(匹配标题、仓库名、作者)
statusstring""按状态过滤(pending / reviewing / completed / failed)
decisionstring""按决策过滤(approve / request_changes / comment / skip)
pageint1页码
per_pageint20每页数量(1-100)

响应字段(items 数组中每个元素):

字段类型说明
idint审查 ID
pr_idintPR ID
repo_namestring | null仓库名
repo_ownerstring | null仓库所有者
authorstring | nullPR 作者
titlestring | nullPR 标题
branchstring | null分支名
file_countint | null文件数
line_countint | null行数
code_file_countint | null代码文件数
strategystring | null审查策略
statusstring | null状态
error_messagestring | null错误信息
review_summarystring | null审查摘要
overall_scoreint | null综合评分
decisionstring | null决策
decision_reasonstring | null决策理由
prompt_tokensint | nullPrompt Token 数
completion_tokensint | nullCompletion Token 数
estimated_costint | null预估费用
created_atstring | null创建时间
updated_atstring | null更新时间
completed_atstring | null完成时间
commentsarray | null评论列表(列表接口为 null)

GET /reviews/export ​

导出 PR 审查列表为 CSV 文件。

认证级别:auth

查询参数:

参数类型默认值说明
searchstring""搜索关键词
statusstring""按状态过滤
decisionstring""按决策过滤

响应:返回 text/csv 文件流,最多 1000 条记录。文件名格式 pr_reviews_YYYYMMDD.csv,UTF-8 BOM 编码。


GET /reviews/ ​

审查详情,含评论列表。

认证级别:auth

路径参数:

参数类型说明
review_idint审查记录 ID

响应字段:

与列表接口相同,额外包含 comments 数组:

字段类型说明
comments[].idint评论 ID
comments[].file_pathstring | null文件路径
comments[].line_numberint | null行号
comments[].comment_typestring | null评论类型
comments[].severitystring | null严重程度
comments[].contentstring | null评论内容
comments[].created_atstring | null创建时间

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "id": 42,
    "pr_id": 128,
    "repo_name": "my-org/my-repo",
    "status": "completed",
    "overall_score": 8,
    "decision": "approve",
    "comments": [
      {
        "id": 101,
        "file_path": "src/main.py",
        "line_number": 42,
        "comment_type": "suggestion",
        "severity": "minor",
        "content": "建议使用 async with 代替 with",
        "created_at": "2026-04-17T10:31:00"
      }
    ]
  }
}

GET /reviews/{review_id}/files ​

审查文件级统计,按 file_path 分组,含严重程度分布。

认证级别:auth

路径参数:

参数类型说明
review_idint审查记录 ID

响应字段(items 数组中每个元素):

字段类型说明
file_pathstring文件路径(__overall__ 表示总体统计)
severity_countsobject严重程度计数
severity_counts.criticalint严重问题数
severity_counts.majorint主要问题数
severity_counts.minorint次要问题数
severity_counts.suggestionint建议数
comment_countint评论总数

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": [
    {
      "file_path": "src/main.py",
      "severity_counts": {
        "critical": 1,
        "major": 2,
        "minor": 3,
        "suggestion": 5
      },
      "comment_count": 11
    }
  ]
}

GET /reviews/{review_id}/comments ​

审查评论列表,可按 file_path 过滤。

认证级别:auth

路径参数:

参数类型说明
review_idint审查记录 ID

查询参数:

参数类型默认值说明
file_pathstring""文件路径过滤(__overall__ 表示总体评论)

响应字段(items 数组中每个元素):

字段类型说明
idint评论 ID
file_pathstring | null文件路径
line_numberint | null行号
comment_typestring | null评论类型
severitystring | null严重程度
contentstring | null评论内容
created_atstring | null创建时间

GET /reviews/{review_id}/files/ ​

获取特定文件的审查评论。

认证级别:auth

路径参数:

参数类型说明
review_idint审查记录 ID
file_pathstring文件路径(URL 编码,支持多级路径)

响应字段:

字段类型说明
data.file_pathstring文件路径
data.comment_countint评论总数
data.comments[]array评论列表
data.comments[].idint评论 ID
data.comments[].line_numberint | null行号
data.comments[].comment_typestring | null评论类型
data.comments[].severitystring | null严重程度
data.comments[].contentstring | null评论内容
data.comments[].created_atstring | null创建时间

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "file_path": "src/main.py",
    "comment_count": 3,
    "comments": [
      {
        "id": 101,
        "line_number": 42,
        "comment_type": "suggestion",
        "severity": "minor",
        "content": "建议使用 async with",
        "created_at": "2026-04-17T10:31:00"
      }
    ]
  }
}

3.6 Issue 分析 ​

GET /issues ​

Issue 分析列表,支持分页、搜索和多维过滤。

认证级别:auth

查询参数:

参数类型默认值说明
searchstring""搜索关键词(匹配标题、仓库名、作者)
repo_namestring""按仓库过滤
categorystring""按分类过滤
prioritystring""按优先级过滤
statusstring""按状态过滤
pageint1页码
per_pageint20每页数量(1-100)

响应字段(items 数组中每个元素):

字段类型说明
idint分析记录 ID
issue_numberintIssue 编号
repo_namestring | null仓库名
repo_ownerstring | null仓库所有者
authorstring | nullIssue 作者
titlestring | nullIssue 标题
categorystring | null分类
prioritystring | null优先级
summarystring | null摘要
feasibilitystring | null可行性评估
suggested_titlestring | null建议标题
suggested_assigneesarray建议指派人列表(JSON 已解析)
suggested_labelsarray建议标签列表(JSON 已解析)
suggested_milestonestring | null建议 Milestone
duplicate_ofint | null重复 Issue 编号
related_prsarray关联 PR 列表(JSON 已解析)
analysis_detailstring | null分析详情
statusstring | null状态
error_messagestring | null错误信息
comment_postedint | null是否已发评论
comment_urlstring | null评论 URL
labels_appliedint | null是否已打标签
applied_label_namesstring | null已打标签名
created_atstring | null创建时间
completed_atstring | null完成时间

GET /issues/stats ​

Issue 统计数据。

认证级别:auth

响应字段:

字段类型说明
data.totalint总数
data.by_categoryobject按分类统计(键为分类名,值为数量)
data.by_priorityobject按优先级统计(键为优先级名,值为数量)
data.by_statusobject按状态统计(键为状态名,值为数量)

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "total": 50,
    "by_category": {"bug": 20, "feature": 15, "question": 10, "other": 5},
    "by_priority": {"high": 10, "medium": 25, "low": 15},
    "by_status": {"completed": 40, "pending": 5, "failed": 5}
  }
}

GET /issues/ ​

Issue 分析详情。

认证级别:auth

路径参数:

参数类型说明
issue_idint分析记录 ID

响应字段:与列表接口每个元素的字段相同,suggested_labels、suggested_assignees、related_prs 为已解析的 JSON 数组。


POST /issues/{issue_id}/reanalyze ​

重新分析 Issue。将提交到后台队列异步执行。

保留成功返回 task_id 的契约,先提交真实钱包及并发入场。余额不足为 HTTP 402/insufficient_credits,并发超限为 HTTP 429/concurrency_limit;缺失 可信付款身份为 403。拒绝响应 success=false,无 task_id,原分析状态不变。 错误遵循当前用户语言,不回显内部异常。关闭 Issue 仍返回 409;交接不可用 或未知为 503,不将未知交接误报为已完成。管理员执行明确由平台承担。

认证级别:auth

路径参数:

参数类型说明
issue_idint分析记录 ID

响应字段:

字段类型说明
data.task_idstring后台任务 ID

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "task_id": "task_abc123"
  }
}

3.7 用户管理 (Users) ​

GET /users ​

用户列表(管理员),支持分页和搜索。

认证级别:admin

查询参数:

参数类型默认值说明
searchstring""搜索关键词(匹配 GitHub 用户名、Telegram ID)
rolestring""按角色过滤(user / admin / super_admin)
pageint1页码
per_pageint20每页数量(1-100)

响应字段(items 数组中每个元素):

字段类型说明
idint用户 ID
telegram_idintTelegram ID
github_usernamestring | nullGitHub 用户名
rolestring角色
daily_quotaint | null每日 PR 配额
weekly_quotaint | null每周 PR 配额
monthly_quotaint | null每月 PR 配额
daily_usedint | null每日已用
weekly_usedint | null每周已用
monthly_usedint | null每月已用
issue_daily_quotaint | null每日 Issue 配额
issue_weekly_quotaint | null每周 Issue 配额
issue_monthly_quotaint | null每月 Issue 配额
issue_daily_usedint | null每日 Issue 已用
issue_weekly_usedint | null每周 Issue 已用
issue_monthly_usedint | null每月 Issue 已用
is_activebool | null是否启用
created_atstring | null创建时间
updated_atstring | null更新时间

POST /users ​

创建用户。

认证级别:super_admin

请求体:

字段类型必填默认值说明
telegram_idint是-Telegram ID(正整数)
github_usernamestring是-GitHub 用户名(非空)
rolestring否"user"角色(user / admin / super_admin)
daily_quotaint否10每日 PR 配额
weekly_quotaint否50每周 PR 配额
monthly_quotaint否200每月 PR 配额
issue_daily_quotaint否20每日 Issue 配额
issue_weekly_quotaint否80每周 Issue 配额
issue_monthly_quotaint否300每月 Issue 配额

响应示例:

json
{
  "success": true,
  "message": "用户 octocat 已成功添加",
  "data": {
    "id": 5,
    "telegram_id": 123456789,
    "github_username": "octocat",
    "role": "user",
    "daily_quota": 10,
    "weekly_quota": 50,
    "monthly_quota": 200,
    "issue_daily_quota": 20,
    "issue_weekly_quota": 80,
    "issue_monthly_quota": 300,
    "daily_used": 0,
    "weekly_used": 0,
    "monthly_used": 0,
    "issue_daily_used": 0,
    "issue_weekly_used": 0,
    "issue_monthly_used": 0,
    "is_active": true,
    "created_at": "2026-04-17T10:00:00",
    "updated_at": "2026-04-17T10:00:00"
  }
}

GET /users/ ​

用户详情,含配额使用历史(最近 20 条)。

认证级别:admin

路径参数:

参数类型说明
user_idint用户 ID

响应字段:包含用户基本字段(同列表) + 额外 usage_logs 数组:

字段类型说明
usage_logs[].idint日志 ID
usage_logs[].quota_typestring配额类型
usage_logs[].used_countint使用次数
usage_logs[].created_atstring | null创建时间

PATCH /users/{user_id}/role ​

修改用户角色。

认证级别:admin(修改 admin/super_admin 角色或设置为 super_admin 需要 super_admin 权限)

路径参数:

参数类型说明
user_idint用户 ID

请求体:

字段类型必填说明
rolestring是新角色(user / admin / super_admin)

响应示例:

json
{
  "success": true,
  "message": "用户角色已更改为 admin"
}

PATCH /users/{user_id}/quota ​

修改用户 PR 配额。

认证级别:admin

路径参数:

参数类型说明
user_idint用户 ID

请求体:

字段类型必填说明
daily_quotaint是每日配额(>= 0)
weekly_quotaint是每周配额(>= 0)
monthly_quotaint是每月配额(>= 0)

响应示例:

json
{
  "success": true,
  "message": "用户配额已更新"
}

PATCH /users/{user_id}/issue-quota ​

修改用户 Issue 配额。

认证级别:admin

路径参数:

参数类型说明
user_idint用户 ID

请求体:

字段类型必填说明
issue_daily_quotaint是每日配额(>= 0)
issue_weekly_quotaint是每周配额(>= 0)
issue_monthly_quotaint是每月配额(>= 0)

响应示例:

json
{
  "success": true,
  "message": "Issue 配额已更新"
}

POST /users/{user_id}/toggle ​

启用/禁用用户(切换 is_active 状态)。

认证级别:admin(操作 admin/super_admin 需要 super_admin 权限)

路径参数:

参数类型说明
user_idint用户 ID

响应示例:

json
{
  "success": true,
  "message": "用户 octocat 已禁用"
}

DELETE /users/ ​

删除用户。

认证级别:super_admin

路径参数:

参数类型说明
user_idint用户 ID

响应示例:

json
{
  "success": true,
  "message": "用户 octocat 已删除"
}

PATCH /users/{user_id}/info ​

修改用户基本信息(Telegram ID 和 GitHub 用户名)。

认证级别:super_admin

路径参数:

参数类型说明
user_idint用户 ID

请求体:

字段类型必填说明
telegram_idint是新 Telegram ID(正整数)
github_usernamestring是新 GitHub 用户名(非空)

响应示例:

json
{
  "success": true,
  "message": "用户基本信息已更新"
}

POST /users/{user_id}/reset-quota ​

重置用户所有配额使用量为 0,并重置所有定时器。

认证级别:super_admin

路径参数:

参数类型说明
user_idint用户 ID

响应示例:

json
{
  "success": true,
  "message": "用户 octocat 的配额使用量已重置"
}

3.8 仓库管理 (Repos) ​

GET /repos ​

仓库列表(含统计数据,如审查数量、索引状态等)。

认证级别:admin

响应字段:返回安装信息列表,具体结构由 GitHub App Installation 数据决定。


POST /repos/{repo_name}/index-docs ​

触发文档索引(RAG)。

认证级别:admin

路径参数:

参数类型说明
repo_namestring仓库名(支持多级路径,如 owner/repo)

前置条件:RAG 功能需在设置中启用。

响应示例:

json
{
  "success": true,
  "message": "文档索引已启动: my-org/my-repo"
}

POST /repos/{repo_name}/index-code ​

触发代码索引。

认证级别:admin

路径参数:

参数类型说明
repo_namestring仓库名(支持多级路径)

前置条件:代码索引功能需在设置中启用。

响应示例:

json
{
  "success": true,
  "message": "代码索引已启动: my-org/my-repo"
}

POST /repos/{repo_name}/index-issues ​

触发 Issues 索引。

认证级别:admin

路径参数:

参数类型说明
repo_namestring仓库名(支持多级路径)

前置条件:语义 Issue 关联功能需在设置中启用。

响应示例:

json
{
  "success": true,
  "message": "Issues 索引已启动: my-org/my-repo"
}

POST /repos/{repo_name}/scan ​

触发仓库安全扫描。

认证级别:super_admin

路径参数:

参数类型说明
repo_namestring仓库名(支持多级路径)

响应示例:

json
{
  "success": true,
  "message": "仓库扫描已启动: my-org/my-repo"
}

3.9 配置管理 (Config) ​

所有配置端点需要 super_admin 权限。敏感字段(含 secret、key、token、password、credential)会被脱敏为 **** 格式。错误响应不暴露内部异常详情,仅返回通用错误消息。

GET /config/ai-providers ​

获取内置 AI 厂商列表,用于 WebUI 配置页或客户端生成下拉选项。

认证级别:super_admin

响应字段:同 GET /setup/ai-providers。


POST /config/ai-providers/{provider}/models ​

按厂商获取模型列表。凭据通过已保存账号解析:请求体必须提供 account_id,服务端使用该账号的 api_base / api_key 获取模型列表。旧式扁平凭据回退(openai_api_key / openai_api_base)已停用。

认证级别:super_admin

限流:10 次/分钟

路径参数:

参数类型说明
providerstringAI 厂商 ID,如 openai、deepseek、qwen、custom

请求体:

字段类型必填说明
account_idstring是已保存 AI 账号 ID(在 WebUI「AI 配置」中创建);凭据从该账号解析

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "success": true,
    "models": ["gpt-4o-mini", "gpt-4o"],
    "context_window_k": 128,
    "message": "获取模型列表成功"
  }
}

GET /config/general ​

获取全局配置。

认证级别:super_admin

响应字段:

字段类型说明
data.configsobject键值对(键为配置名,值为配置值,敏感值已脱敏;包括数据库中保存的动态配置)

常见可配置键包括:

配置键说明
openai_api_key / openai_api_base / openai_model已废弃 - 请通过 WebUI 「AI 配置」角色绑定配置(main/summary/agent_team)
output_languageAI 输出语言配置
init_user_daily_quota / init_user_weekly_quota / init_user_monthly_quota自注册用户基础 PR 配额
init_user_issue_daily_quota / init_user_issue_weekly_quota / init_user_issue_monthly_quota自注册用户基础 Issue 配额
init_admin_agent_daily_quota / init_admin_agent_weekly_quota / init_admin_agent_monthly_quotaSetup 初始管理员 Agent 配额
init_user_agent_daily_quota / init_user_agent_weekly_quota / init_user_agent_monthly_quota自注册用户基础 Agent 配额

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "configs": {
      "OPENAI_API_KEY": "sk-1****abcd",
      "OPENAI_MODEL": "gpt-4o",
      "APP_DOMAIN": "example.com"
    }
  }
}

PATCH /config/general ​

更新全局配置。配置值按既有契约使用字符串(布尔使用 "true" / "false");计费参数先校验,再保存。

认证级别:super_admin

请求体:

字段类型必填说明
configsobject是键值对,键为配置名,值为新值

请求示例:

json
{
  "configs": {
    "billing_enabled": "false",
    "billing_initial_reserve_credits": "500",
    "billing_reservation_ttl_seconds": "3600"
  }
}

响应示例:

json
{
  "success": true,
  "message": "配置已更新"
}

计费及策略/标签校验错误返回 HTTP 400,保留 success=false / error,增加稳定 code 和 errors 数组。每项包含 field、code、按可信用户个人偏好翻译的 message、安全约束 params;可提供 details、help_url、help_label。 例如缺少模型报价时 field=billing_enabled、code=missing_price,列出缺失 Provider/Model/call_kind 并链接 /billing/admin/pricing。Bearer 客户端也按自身 用户ID读取语言,不依赖 WebUI Cookie。错误不返回提交的原始字段值或完整模板。

WebUI /config/save-all 保留 ok/toast/results 契约,并在失败分区及顶层聚合 errors。部分失败保持 ok=false,成功分区仍独立记录。单表单请求在 Accept: application/json 下使用 HTTP 400/200 JSON反馈;普通提交保留302并携 _errors供同页定位。

GET /config/strategies ​

获取策略配置。

认证级别:super_admin

响应字段:

字段类型说明
data.strategiesobject策略配置(数据库 strategy.* 节键,与内置默认深度合并)

PATCH /config/strategies/ ​

更新策略配置的某个 section。

认证级别:super_admin

路径参数:

参数类型说明
sectionstring策略 section 名称(如 strategies、file_filters、context_enhancement、review_policy、issue_analysis、depgraph、pr_summary)

请求体:

字段类型必填说明
dataobject是要更新的键值对

请求示例:

json
{
  "data": {
    "max_files": 30,
    "focus_areas": ["security", "performance"]
  }
}

响应示例:

json
{
  "success": true,
  "message": "策略配置 standard 已更新"
}

GET /config/labels ​

获取标签配置。

认证级别:super_admin

响应字段:

字段类型说明
data.labelsarray标签定义列表
data.recommendationobject标签推荐设置

PUT /config/labels ​

更新标签定义(全量覆盖)。

认证级别:super_admin

请求体:

字段类型必填说明
labelsarray是新的标签定义列表(非空)

响应示例:

json
{
  "success": true,
  "message": "标签定义已更新"
}

PATCH /config/labels/recommendation ​

更新标签推荐设置。

认证级别:super_admin

请求体:

字段类型必填说明
recommendationobject是推荐设置(非空)

响应示例:

json
{
  "success": true,
  "message": "标签推荐设置已更新"
}

3.10 日志查询 (Logs) ​

GET /logs/reviews ​

审查日志列表,支持分页、搜索和多维过滤。

认证级别:auth

查询参数:

参数类型默认值说明
searchstring""搜索关键词(匹配标题、仓库名、作者)
repostring""按仓库过滤
statusstring""按状态过滤
date_fromstring""开始日期(YYYY-MM-DD,无效格式返回 400)
date_tostring""结束日期(YYYY-MM-DD,包含当天全天,无效格式返回 400)
pageint1页码
per_pageint20每页数量(1-100)

响应字段(items 数组中每个元素):

字段类型说明
idint审查 ID
pr_idintPR ID
repo_namestring仓库名
repo_ownerstring仓库所有者
titlestringPR 标题
authorstring作者
statusstring状态
decisionstring决策
overall_scoreint评分
strategystring策略
created_atstring创建时间
completed_atstring完成时间

GET /logs/reviews/ ​

审查日志详情。

认证级别:auth

路径参数:

参数类型说明
review_idint审查 ID

响应字段:

字段类型说明
data.idint审查 ID
data.pr_idintPR ID
data.repo_namestring仓库名
data.repo_ownerstring仓库所有者
data.titlestringPR 标题
data.authorstring作者
data.statusstring状态
data.decisionstring决策
data.overall_scoreint评分
data.review_summarystring审查摘要
data.error_messagestring错误信息
data.strategystring策略
data.prompt_tokensintPrompt Token 数
data.completion_tokensintCompletion Token 数
data.created_atstring创建时间
data.completed_atstring完成时间
data.comments[]array评论列表
data.comments[].idint评论 ID
data.comments[].file_pathstring文件路径
data.comments[].line_numberint行号
data.comments[].severitystring严重程度
data.comments[].contentstring内容

GET /logs/actions ​

操作日志列表(管理员)。

认证级别:admin

查询参数:

参数类型默认值说明
actionstring""操作类型过滤
start_datestring""开始日期(YYYY-MM-DD,无效格式返回 400)
end_datestring""结束日期(YYYY-MM-DD,包含当天全天,无效格式返回 400)
pageint1页码
per_pageint20每页数量(1-100)

响应字段(items 数组中每个元素):

字段类型说明
idint日志 ID
admin_idint操作人 ID
actionstring操作类型
target_typestring目标类型
target_idstring目标 ID
detailstring详细信息
created_atstring创建时间

GET /logs/actions/ ​

操作日志详情。

认证级别:admin

路径参数:

参数类型说明
log_idint日志 ID

响应字段:

字段类型说明
data.idint日志 ID
data.admin_idint操作人 ID
data.admin_usernamestring | null操作人 GitHub 用户名
data.actionstring操作类型
data.target_typestring目标类型
data.target_idstring目标 ID
data.detailstring详细信息
data.created_atstring创建时间

3.11 队列监控 (Queue) ​

GET /queue/stats ​

队列统计数据。

认证级别:admin

响应字段:

字段类型说明
data.pendingint待处理数
data.processingint处理中数
data.completedint已完成数
data.failedint失败数
data.totalint总数

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "pending": 5,
    "processing": 2,
    "completed": 150,
    "failed": 3,
    "total": 160
  }
}

GET /queue/items ​

队列列表,支持分页和过滤。

认证级别:admin

查询参数:

参数类型默认值说明
searchstring""搜索关键词(匹配仓库名)
repostring""仓库名过滤
statusstring""状态过滤
pageint1页码
per_pageint20每页数量(1-100)

响应字段(items 数组中每个元素):

字段类型说明
idint队列项 ID
pr_idintPR ID
repo_namestring仓库名
actionstring操作类型
priorityint优先级
statusstring状态
retry_countint重试次数
max_retriesint最大重试次数
error_messagestring错误信息
created_atstring创建时间
updated_atstring更新时间

GET /queue/items/ ​

队列项详情。

认证级别:admin

路径参数:

参数类型说明
item_idint队列项 ID

响应字段:与列表接口每个元素的字段相同。


POST /queue/items/{item_id}/retry ​

重试失败的队列项。

认证级别:admin

路径参数:

参数类型说明
item_idint队列项 ID

前置条件:队列项状态必须为 failed。

响应示例:

json
{
  "success": true,
  "message": "队列项已重新加入队列"
}

DELETE /queue/items/ ​

删除队列项。

认证级别:admin

路径参数:

参数类型说明
item_idint队列项 ID

响应示例:

json
{
  "success": true,
  "message": "队列项已删除"
}

POST /queue/purge ​

批量清理已完成或失败的队列项。

认证级别:admin

查询参数:

参数类型默认值说明
statusstring"completed"清理状态(completed / failed)

响应字段:

字段类型说明
data.deletedint已删除数量

响应示例:

json
{
  "success": true,
  "message": "已清理 50 个已完成的队列项",
  "data": {
    "deleted": 50
  }
}

3.12 扫描管理 (Scans) ​

GET /scans ​

扫描列表,支持分页和过滤。

认证级别:admin

查询参数:

参数类型默认值说明
searchstring""搜索关键词(匹配仓库名)
repo_namestring""按仓库过滤
statusstring""按状态过滤
pageint1页码
per_pageint20每页数量(1-100)

响应字段(items 数组中每个元素):

字段类型说明
idint扫描 ID
repo_namestring仓库名
repo_ownerstring仓库所有者
trigger_typestring触发类型
statusstring状态
progressint进度百分比
total_findingsint发现总数
overall_health_scoreint健康评分
created_atstring创建时间
completed_atstring完成时间

GET /scans/stats ​

扫描统计数据。

认证级别:admin

响应字段:

字段类型说明
data.totalint扫描总数
data.by_statusobject按状态统计
data.avg_health_scorefloat | null平均健康评分

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "total": 25,
    "by_status": {
      "completed": 20,
      "pending": 2,
      "failed": 3
    },
    "avg_health_score": 78.5
  }
}

GET /scans/ ​

扫描详情,含所有发现(findings)。

认证级别:admin

路径参数:

参数类型说明
scan_idint扫描 ID

响应字段:

字段类型说明
data.idint扫描 ID
data.repo_namestring仓库名
data.repo_ownerstring仓库所有者
data.trigger_typestring触发类型
data.triggered_bystring触发者
data.commit_shastring提交 SHA
data.statusstring状态
data.progressint进度
data.current_phasestring当前阶段
data.error_messagestring错误信息
data.file_countint文件数
data.code_file_countint代码文件数
data.total_findingsint发现总数
data.critical_countint严重问题数
data.major_countint主要问题数
data.minor_countint次要问题数
data.suggestion_countint建议数
data.overall_health_scoreint健康评分
data.report_issue_numberint报告 Issue 编号
data.report_issue_urlstring报告 Issue URL
data.created_atstring创建时间
data.started_atstring开始时间
data.completed_atstring完成时间
data.findings[]array发现列表
data.findings[].idint发现 ID
data.findings[].file_pathstring文件路径
data.findings[].line_startint起始行
data.findings[].line_endint结束行
data.findings[].severitystring严重程度
data.findings[].categorystring分类
data.findings[].titlestring标题
data.findings[].descriptionstring描述
data.findings[].suggestionstring建议
data.findings[].confidenceint置信度

POST /scans/trigger ​

手动触发扫描。自动选择未在冷却期内的仓库(最多 5 个)。

认证级别:super_admin

限流:3 次/分钟

响应字段:

字段类型说明
data.triggeredarray已触发的扫描列表
data.triggered[].repostring仓库名
data.triggered[].scan_idint扫描 ID
data.countint已触发数量

响应示例:

json
{
  "success": true,
  "message": "已触发 3 个仓库扫描",
  "data": {
    "triggered": [
      {"repo": "my-org/repo-a", "scan_id": 101},
      {"repo": "my-org/repo-b", "scan_id": 102},
      {"repo": "my-org/repo-c", "scan_id": 103}
    ],
    "count": 3
  }
}

POST /scans/{scan_id}/retry ​

重试失败的扫描。

认证级别:super_admin

路径参数:

参数类型说明
scan_idint扫描 ID

前置条件:扫描状态必须为 failed。

响应示例:

json
{
  "success": true,
  "message": "扫描已重新触发"
}

POST /scans/{scan_id}/cancel ​

取消正在进行的扫描。

认证级别:super_admin

路径参数:

参数类型说明
scan_idint扫描 ID

前置条件:扫描状态必须为 pending、indexing、analyzing 或 reporting。

行为说明:除更新数据库状态外,还会尝试取消正在运行的 asyncio 后台任务,确保扫描进程立即终止。

json
{
  "success": true,
  "message": "扫描已取消"
}

3.13 个人设置 (Settings) ​

GET /settings ​

获取个人偏好设置。

认证级别:auth

响应字段:

字段类型说明
data.themestring主题("light" / "dark" / "system")
data.languagestring语言(如 "zh-CN")
data.items_per_pageint每页数量(10 / 20 / 50 / 100)

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "theme": "system",
    "language": "zh-CN",
    "items_per_page": 20
  }
}

PATCH /settings ​

更新个人偏好设置。

认证级别:auth

请求体(所有字段均为可选,仅传需要更新的字段):

字段类型可选值说明
themestring"light" / "dark" / "system"主题
languagestring任意语言设置
items_per_pageint10 / 20 / 50 / 100每页数量

请求示例:

json
{
  "theme": "dark",
  "items_per_page": 50
}

响应示例:

json
{
  "success": true,
  "message": "设置已更新"
}

GET /settings/about ​

获取系统版本信息。

认证级别:auth

响应字段:

字段类型说明
data.versionstring应用版本号
data.build_datestring构建日期(YYYY-MM-DD)

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "version": "2.12.0",
    "build_date": "2026-05-11"
  }
}

3.14 用户级配置 (User Config) ​

用户级配置用于让普通用户覆盖被系统允许的偏好配置。当前仅开放 output_language,用于控制该用户触发的 AI 输出语言。配置解析顺序为:UserConfig → AppConfig → Settings 默认值。

GET /user-config ​

获取当前用户可覆盖的配置项及其有效值。

认证级别:auth

响应字段:

字段类型说明
data.configsarray配置项状态列表
data.configs[].keystring配置键
data.configs[].labelstring展示名称
data.configs[].descriptionstring配置说明
data.configs[].input_typestring输入类型,如 select
data.configs[].optionsarray可选项列表
data.configs[].user_valuestring | null用户覆盖值;为 null 表示未覆盖
data.configs[].global_valuestring全局配置值
data.configs[].effective_valuestring当前实际生效值
data.configs[].is_overriddenbool是否存在用户覆盖

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "configs": [
      {
        "key": "output_language",
        "label": "输出语言",
        "description": "AI 评论和报告使用的语言",
        "input_type": "select",
        "options": [
          {"value": "", "label": "跟随全局"},
          {"value": "zh-CN", "label": "简体中文"},
          {"value": "en", "label": "English"}
        ],
        "user_value": "en",
        "global_value": "zh-CN",
        "effective_value": "en",
        "is_overridden": true
      }
    ]
  }
}

PATCH /user-config ​

更新当前用户的配置覆盖。传入 null 表示删除该用户覆盖值并回退到全局配置。

认证级别:auth

请求体:

字段类型必填说明
configsobject是键值对,当前仅允许 output_language

请求示例(设置英文输出):

json
{
  "configs": {
    "output_language": "en"
  }
}

请求示例(删除覆盖,回退全局):

json
{
  "configs": {
    "output_language": null
  }
}

响应示例:

json
{
  "success": true,
  "message": "配置已更新"
}

校验规则:

配置键允许值说明
output_language"" / "zh-CN" / "en" / null空字符串或 null 表示跟随全局配置

GET /user-config/metadata ​

获取用户可配置项元数据,适合客户端构建表单。

认证级别:auth

响应示例:

json
{
  "success": true,
  "message": "ok",
  "data": {
    "allowed_keys": ["output_language"],
    "options": {
      "output_language": [
        {"value": "", "label": "跟随全局"},
        {"value": "zh-CN", "label": "简体中文"},
        {"value": "en", "label": "English"}
      ]
    }
  }
}

3.15 付费配额 (Billing) ​

支付及旧套餐购买端点由 payment_enabled 控制。Billing 2.0 钱包、账单、Usage、通知与管理定价/发放独立可用;实际 Usage 收费由 billing_enabled 控制,默认关闭。当前 Billing 模块部分响应为直接 JSON,不完全使用统一 success_response 包装。

Billing 2.0 契约 ​

方法路径(前缀 /api/v1)权限 / 参数
GET/billing/wallet当前用户;balance/reserved/available/low_balance_threshold 都为精确十进制字符串
PUT/billing/wallet/threshold当前用户;credits 为最多六位小数的字符串,0 禁用提醒
GET/billing/transactions当前用户;kind/feature/offset/limit 筛选及分页;只显示有权访问的业务来源
GET/billing/operations当前用户;status/feature/offset/limit;包含待结算/待核对执行
GET/billing/usage当前用户;operation_id/feature/offset/limit;实际 Token 保留 null 与 0 的区别
GET/billing/notices当前用户;offset/limit,持久化低余额提醒
POST/billing/notices/{notice_id}/read当前用户标记自己的提醒已读,不越权访问他人提醒
GET / POST/billing/admin/pricingsuper_admin;POST account_id/model_id/call_kind/config 发布账号的新不可变版本,provider_id 从账号解析;无 account_id 时保留旧显式 provider_id 契约
POST/billing/admin/wallets/{user_id}/adjustsuper_admin;精确 credits、idempotency_key、reason,操作者取鉴权上下文
GET/billing/admin/payment-eventssuper_admin;offset/limit 分页查看已验签但待核对的支付/退款事件,金额未知为 null
POST/billing/admin/payment-events/{event_id}/replaysuper_admin;只重放本地已保存证据,不再次请求支付/退款网关;返回实际 status/pending_reason
POST/billing/admin/payment-events/{event_id}/resolvesuper_admin;必填 evidence,可提供 order_id、checkout_amount_cents/checkout_currency 或 refund_reference_id/refund_amount_cents/refund_currency;按审核证据核对并重放

套餐创建/编辑与返回增加 credit_grant(Decimal 字符串)、rate_limits(已验证 JSON 映射)、concurrency_limit。旧 bonus 字段为独立可消耗权益,不再永久修改每日上限。购买按订单快照发放,套餐修改不改变已购权益。POST /billing/admin/grant 支持 body idempotency_key 或 Idempotency-Key 头;同时提供须相同。兼容旧无键请求,为每次独立请求生成并返回 UUID,后续重试必须沿用返回键以去重。退款使用稳定请求键,上限 160 字符。部分退款仅在显式配置 proportional_unused_credits 后用于 Credits-only 套餐,默认拒绝不明确的比例政策。

更新套餐省略 concurrency_limit 保持原值,显式传 null 清除此套餐的并发上限;WebUI 显式提交空白也可清除。

concurrency_limit 是每用户跨 PR/Issue/Agent/Repo Scan 的业务执行入场上限: 已登记并排队/运行的 outcome=null 执行占用,已记录终态结果即释放,账单是否 结算不影响此口径。新登记及已结束执行的恢复都会检查上限。服务侧的 max_concurrent_reviews/max_concurrent_issues/agent_team_max_concurrent 使用共享 数据库协调所有 API/Worker 实例的执行容量,满额排队,不代表用户购买的余额。

price_cents/amount_cents/refunded_amount_cents 保持整数契约,表示所选币种的最小单位(JPY 0 位、USD/CNY 2 位、USDT 6 位)。新增 formatted_price/formatted_amount/formatted_refunded_amount 精确字符串用于显示,客户端不能统一除以 100。 历史未知币种保留原整数/code,格式化金额为 null 并返回 currency_supported=false,禁止猜测小数位。Alipay 国内 page.pay 结账仅支持 CNY。

余额不足使用 insufficient_credits,次数/并发为独立限流提示。管理员价格配置必须显式指定成本/结算币种、汇率、markup、Credits 换算及 Token 或实际计量单价,不能用浮点样本启用。详情见 Billing 2.0。

POST /queue/increments/{item_id}/resume 仅活跃超级管理员可恢复已验证未执行的 PR 增量派发。body 必须包含非空 evidence(最多 2000 字符)、reason(最多 1000 字符),拒绝额外字段。付款者和 operation 取已保存的队列载体,不接受 客户端指定。返回 ready/resume_requested、leased/owned、terminal 或 pending_reconciliation 等实际恢复结果;未知外部请求不自动重发。仓库无现有 GitHub App 访问权限返回可重试错误,PR 已关闭会取消未使用执行并追加管理审计。 恢复 CLI 的默认 dry-run、审核清单与切换边界见 Billing 2.0。

报价返回增加 account_id(历史/独立辅助模型为 null)和 scope_key。新账号调用 严格按实际命中的账号查价,不回退到旧 Provider 通用报价。主调用、压缩、流式及 Fallback 的 Usage 和计价快照保存实际账号;历史冻结费用不因账号改名或报价 变更而改写。

新报价中 chat 同时覆盖流式与非流式模型调用;请求 chat_stream 是兼容 别名,发布后保存 chat,管理员审计另外保留 requested_call_kind。原始 Usage 和实际请求类型不改变;计价快照保存 pricing_call_kind/price_profile_call_kind。 历史已固定的旧流式报价继续按原版本结算,不自动选择旧流式报价用于新请求。 报价成本/结算币种及套餐付款币种均按统一支持目录验证,目录外代码不能通过 JSON/API 绕过下拉。币种参数规范化为大写,USDT 保留现有六位最小单位语义。

WebUI 超级管理员模型发现接口(没有 /api/v1 前缀)为 GET /billing/admin/pricing/accounts/{account_id}/models?refresh=false。 账号须已配置且启用;服务端读取其凭据,仅调用模型列表接口。成功返回 {success:true,data:{account_id,models,default_model,source,discovery_failed}}, models 是该账号保存/默认/发现的模型 ID 列表,source 为 saved/discovered/cached。 发现失败保留该账号已保存的模型,discovery_failed=true;凭据、端点与上游错误 正文不返回。缓存60秒,refresh=true 强制重新发现。仅超级管理员可访问,支付 关闭时仍可配置报价。WebUI 表单的 source_scope=account 必须有 account_id; embedding/rerank 来源由当前独立服务配置解析 Provider/模型/调用类型。

支付回调先保存不可变 received 审计,再处理账务。已验签但无法归一化的金额/币种保留最小 wire_evidence,进入 pending_reconciliation,不当作免费或忽略事件;人工核对追加 reviewed 审计,保留原始证据供重投递比较。退款引用与通道事件均有数据库幂等约束。后台 /billing/admin/pricing 提供待核对列表和 CSRF 保护的重放/核对表单。

2.12.0 起,Billing API 支持外部支付订单创建和查询,provider 可使用 stripe、paddle、alipay、nowpayments、tron。兑换码和管理员手动发放仍可用于无需外部支付网关的配额发放。

GET /billing/plans ​

列出当前可用套餐。

认证级别:auth

响应示例:

json
[
  {
    "id": 1,
    "name": "Pro 月度包",
    "plan_type": "subscription",
    "price_cents": 990,
    "currency": "CNY",
    "duration_days": 30,
    "pr_quota_bonus": 0,
    "pr_daily_add": 10,
    "pr_weekly_add": 0,
    "pr_monthly_add": 0,
    "issue_quota_bonus": 0,
    "issue_daily_add": 20,
    "issue_weekly_add": 0,
    "issue_monthly_add": 0,
    "description": "月度订阅套餐"
  }
]

POST /billing/redeem ​

兑换配额兑换码。

认证级别:auth

请求体:

字段类型必填说明
codestring是兑换码

响应示例:

json
{
  "success": true,
  "order_no": "ORD202605090001",
  "plan_name": "Pro 月度包"
}

GET /billing/orders ​

获取当前用户订单历史。

认证级别:auth

查询参数:

参数类型默认值范围说明
limitint201-100返回数量
offsetint0>= 0偏移量

响应示例:

json
{
  "total": 1,
  "orders": [
    {
      "id": 1,
      "order_no": "ORD202605090001",
      "plan_name": "Pro 月度包",
      "amount_cents": 990,
      "currency": "CNY",
      "status": "paid",
      "payment_provider": "redeem_code",
      "created_at": "2026-05-09T12:00:00",
      "fulfilled_at": "2026-05-09T12:00:01"
    }
  ]
}

POST /billing/orders ​

创建外部支付订单并返回支付跳转地址。适用于 Stripe、Paddle、支付宝、NOWPayments 和 TRON USDT 等已启用网关。

认证级别:auth

请求体:

字段类型必填默认值说明
plan_idint是-要购买的套餐 ID
providerstring否"stripe"支付网关:stripe / paddle / alipay / nowpayments / tron

响应示例:

json
{
  "success": true,
  "order_no": "ORD202605280001",
  "status": "pending",
  "amount_cents": 990,
  "currency": "CNY",
  "provider": "alipay",
  "checkout_url": "https://openapi.alipay.com/gateway.do?...",
  "expires_at": "2026-05-28T12:30:00+00:00"
}

GET /billing/orders/ ​

查询当前用户自己的订单状态,并返回可继续支付的 checkout URL(如果订单元数据中存在)。

认证级别:auth

路径参数:

参数类型说明
order_idint订单 ID

响应示例:

json
{
  "id": 1,
  "order_no": "ORD202605280001",
  "status": "pending",
  "amount_cents": 990,
  "currency": "CNY",
  "payment_provider": "alipay",
  "provider_tx_id": null,
  "checkout_url": "https://openapi.alipay.com/gateway.do?...",
  "paid_at": null,
  "fulfilled_at": null,
  "created_at": "2026-05-28T12:00:00",
  "expires_at": "2026-05-28T12:30:00+00:00"
}

POST /billing/orders/{order_id}/refund ​

超级管理员直接对订单执行退款。WebUI 中还提供用户退款申请与超级管理员审核流程;该 API 端点用于管理员侧直接退款。

认证级别:super_admin

路径参数:

参数类型说明
order_idint订单 ID

请求体:

字段类型必填说明
amount_centsint | null否退款金额(分);为空时按服务逻辑执行默认退款金额

响应示例:

json
{
  "success": true,
  "order_no": "ORD202605280001",
  "status": "refunded"
}

POST /billing/admin/plans ​

创建套餐。

认证级别:super_admin

请求体字段:

字段类型必填说明
namestring是套餐名称
plan_typestring是one_time 或 subscription
price_centsint否价格(分)
currencystring否货币,默认 CNY
duration_daysint | null否有效天数
pr_quota_bonus / issue_quota_bonusint否一次性配额增量
pr_daily_add / issue_daily_addint否每日配额增量
pr_weekly_add / issue_weekly_addint否每周配额增量
pr_monthly_add / issue_monthly_addint否每月配额增量
descriptionstring | null否套餐描述
sort_orderint否排序值

响应示例:

json
{
  "id": 1,
  "name": "Pro 月度包"
}

PUT /billing/admin/plans/ ​

编辑现有套餐。

认证级别:super_admin

路径参数:

参数类型说明
plan_idint套餐 ID

请求体字段:同创建套餐(POST /billing/admin/plans),所有字段可选,仅传递需要修改的字段。

响应示例:

json
{
  "id": 1,
  "name": "Pro 月度包(更新)"
}

DELETE /billing/admin/plans/ ​

删除套餐。默认软删除;传入 hard=true 时从数据库硬删除。

认证级别:super_admin

路径参数:

参数类型说明
plan_idint套餐 ID

查询参数:

参数类型默认值说明
hardboolfalse是否硬删除

响应示例:

json
{
  "success": true,
  "id": 1,
  "name": "Pro 月度包",
  "hard_delete": false
}

PUT /billing/admin/codes/ ​

编辑兑换码(状态、过期时间、最大使用次数)。

认证级别:super_admin

路径参数:

参数类型说明
code_idint兑换码 ID

请求体字段:

字段类型必填说明
statusstring否兑换码状态:active / disabled
expires_atstring | null否过期时间
max_usesint否最大使用次数
plan_idint否绑定的新套餐 ID

DELETE /billing/admin/codes/ ​

删除兑换码。

认证级别:super_admin

路径参数:

参数类型说明
code_idint兑换码 ID

响应示例:

json
{
  "success": true,
  "id": 1,
  "code": "SAKURA-ABCD"
}

POST /billing/admin/codes/generate ​

批量生成兑换码。

认证级别:super_admin

请求体:

字段类型必填说明
plan_idint是套餐 ID
countint是生成数量,1-100
batch_namestring | null否批次名称
max_usesint否每个兑换码最大使用次数,默认 1

响应示例:

json
{
  "count": 2,
  "codes": ["SAKURA-ABCD", "SAKURA-EFGH"]
}

POST /billing/admin/grant ​

管理员手动为用户发放套餐权益。

认证级别:super_admin

请求体:

字段类型必填说明
user_idint是目标用户 ID
plan_idint是套餐 ID
idempotency_keystring否稳定事件键(也可通过 Idempotency-Key 请求头提供);缺省为本次请求生成 UUID,并在响应返回

响应示例:

json
{
  "success": true,
  "order_no": "ORD202605090002",
  "idempotency_key": "b287bc7b-987a-4d88-8bb9-c9612367e970"
}

3.16 SSE 事件流 (Events) ​

GET /events ​

SSE(Server-Sent Events)实时事件流。

认证级别:auth

连接方式:

  • 通过 URL 查询参数传递 Token:GET /api/v1/events?token=<jwt_token>
  • 或通过 Authorization: Bearer <token> Header

Android 接入建议:使用 OkHttp 或 Kotlin Coroutines Flow 建立 SSE 连接。注意 SSE 连接是长连接,需在后台妥善管理生命周期。

响应头:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
X-Accel-Buffering: no

事件格式(标准 SSE):

event: review_completed
data: {"review_id": 42, "repo_name": "my-org/my-repo", ...}

event: scan_progress
data: {"scan_id": 101, "progress": 50, ...}

: keepalive

Keepalive:每 30 秒发送一次 : keepalive\n\n 注释行,防止连接被代理/负载均衡器因超时断开。


4. Android 接入快速指南 ​

OAuth 登录流程 ​

1. GET /api/v1/auth/github/mobile?redirect_uri=myapp://oauth/callback
   -> 获取 authorization_url 和 state

2. 打开浏览器,加载 authorization_url
   -> 用户在 GitHub 授权

3. GitHub 回调到 myapp://oauth/callback?code=xxx&state=xxx
   -> App 接收 code 和 state

4. POST /api/v1/auth/callback
   Body: {"code": "xxx", "state": "xxx"}
  -> 获取 access_token,或在用户启用 MFA 时获取 mfa_token

5. 如返回 message="mfa_required":
   - TOTP/恢复码:POST /api/v1/auth/2fa/verify
     Body: {"mfa_token": "xxx", "code": "123456"}
   - Passkey:POST /api/v1/auth/2fa/passkey/options
     Body: {"mfa_token": "xxx"}
     -> 使用 public_key 发起 WebAuthn 认证
     POST /api/v1/auth/2fa/passkey/verify
     Body: {"mfa_token": "xxx", "challenge_id": "xxx", "credential": {...}}
   -> 获取正式 access_token

6. 后续请求: Authorization: Bearer <access_token>

常用请求模板 ​

kotlin
// OkHttp 请求构建
val request = Request.Builder()
    .url("https://your-domain/api/v1/dashboard/stats")
    .header("Authorization", "Bearer $token")
    .build()

SSE 连接示例 ​

kotlin
// 使用 OkHttp SSE
val request = Request.Builder()
    .url("https://your-domain/api/v1/events")
    .header("Authorization", "Bearer $token")
    .build()

val sseSource = EventSource.Factory.create(request, eventListener)

SSE 认证方式:支持三种认证 —— Authorization: Bearer <token> Header、Cookie: webui_token=<token>、以及 ?token=<jwt_token> 查询参数(适用于部分不支持自定义 Header 的 SSE 客户端)。


Documentation version: v1.3 | Last updated: 2026-05-21 | Total endpoints: 86


Last updated: 2026-10-8 · Found an error? Submit an Issue

Sakura AI 开源项目 · 文档内容与项目版本同步维护