19 KiB
风控模块接口文档
文档信息
| 项目 | 内容 |
|---|---|
| 文档版本 | v1.0 |
| 编制日期 | 2026-09-14 |
| 接口前缀 | /api/v1/risk |
| Agent 接口 | /api/v1/agent-runs |
| 适用对象 | 主项目后端、前端、联调和测试人员 |
| 实现基线 | 当前 RM2_develop 风控模块代码 |
1. 通用约定
1.1 编码与鉴权
- 请求和响应使用 UTF-8。
- JSON 请求使用
Content-Type: application/json。 - 鉴权使用
Authorization: Bearer <JWT>。 - 用户、角色、权限和客户数据范围由服务端实时解析,客户端不能提交这些字段。
1.2 成功响应信封
资源类响应:
{
"data": {},
"meta": {
"trace_id": "trace-id"
}
}
列表类响应:
{
"data": [],
"meta": {
"trace_id": "trace-id",
"next_cursor": "opaque-cursor-or-null",
"has_more": false,
"total": 15,
"page_size": 10
}
}
1.3 错误响应
{
"error": {
"code": "AGENT_PERMISSION_DENIED",
"message": "缺少操作权限",
"trace_id": "trace-id",
"retryable": false
}
}
常用错误:
| HTTP | 错误码 | 含义 |
|---|---|---|
| 400 | INVALID_CURSOR |
游标无效或与当前查询不匹配 |
| 401 | AUTHENTICATION_REQUIRED |
未登录或令牌无效 |
| 403 | AGENT_PERMISSION_DENIED |
缺少权限或数据范围不允许 |
| 404 | SESSION_NOT_FOUND |
资源不存在或不可见 |
| 406 | SSE_NOT_ACCEPTABLE |
SSE 接口未接受 text/event-stream |
| 409 | IDEMPOTENCY_CONFLICT |
幂等键对应了不同请求 |
| 409 | RUN_NOT_CANCELLABLE |
当前状态不允许执行操作 |
| 413 | AGENT_INPUT_INVALID |
上传文件超过大小限制 |
| 422 | AGENT_INPUT_INVALID |
请求字段或业务输入不合法 |
| 429 | RATE_LIMITED |
请求超过限流 |
| 503 | DEPENDENCY_UNAVAILABLE |
依赖服务不可用 |
| 504 | UPSTREAM_TIMEOUT |
上游服务超时 |
1.4 幂等
除证据上传外,风控写接口必须携带:
Idempotency-Key: <16-128 位 ASCII 字符串>
幂等范围为:
user_id + method + normalized_path + idempotency_key
重复请求返回首次响应;同一键对应不同正文返回 409 IDEMPOTENCY_CONFLICT。
1.5 分页
- 预警队列和其他列表:每页最多 10 条。
- 游标绑定用户、筛选条件和数据范围。
- 客户端应原样回传
meta.next_cursor。 - 风控列表接口在
meta中返回total和page_size,用于展示总条数和总页数。
1.6 时间与脱敏
- 请求时间按北京时间解释。
- 响应时间为 ISO 8601 UTC 格式。
- 客户姓名只返回脱敏值。
- 手机号使用脱敏字段。
- 不返回密码、密钥和完整敏感信息。
2. 权限
| 权限码 | 覆盖接口 |
|---|---|
risk:alert:read |
概览、预警、详情、证据、通知、日报、Agent 只读工具 |
risk:alert:write |
确认、调查、误报关闭、完成结案、升级、证据归档 |
risk:alert:scan |
手动规则扫描 |
risk:report:mail |
日报邮件发送 |
agent:run |
创建奶龙风控智能助手运行 |
3. 接口总览
| 方法 | 路径 | 说明 | 权限 |
|---|---|---|---|
| GET | /api/v1/risk/overview |
风险概览 | risk:alert:read |
| GET | /api/v1/risk/alerts |
预警队列 | risk:alert:read |
| GET | /api/v1/risk/alerts/{alert_no} |
预警详情 | risk:alert:read |
| POST | /api/v1/risk/alerts/scan |
手动规则扫描 | risk:alert:scan |
| POST | /api/v1/risk/alerts/{alert_no}/acknowledgements |
确认接收 | risk:alert:write |
| POST | /api/v1/risk/alerts/{alert_no}/investigations |
进入调查 | risk:alert:write |
| POST | /api/v1/risk/alerts/{alert_no}/exclusions |
关闭误报 | risk:alert:write |
| POST | /api/v1/risk/alerts/{alert_no}/resolutions |
完成结案 | risk:alert:write |
| POST | /api/v1/risk/alerts/{alert_no}/escalations |
升级处理 | risk:alert:write |
| POST | /api/v1/risk/alerts/{alert_no}/evidence |
上传并归档证据 | risk:alert:write |
| GET | /api/v1/risk/evidence/{source} |
查询八类证据 | risk:alert:read |
| GET | /api/v1/risk/notifications |
查询通知记录 | risk:alert:read |
| POST | /api/v1/risk/daily-report |
生成结构化日报 | risk:alert:read |
| POST | /api/v1/risk/daily-report/stream |
流式生成日报 | risk:alert:read |
| POST | /api/v1/risk/daily-report/mail |
发送日报邮件 | risk:report:mail |
| POST | /api/v1/agent-runs |
创建风控 Agent 运行 | agent:run + risk:alert:read |
| GET | /api/v1/agent-runs/{run_id} |
查询 Agent 运行结果 | 运行所有者或数据范围 |
| GET | /api/v1/agent-runs/{run_id}/events |
订阅 Agent SSE | 运行所有者或数据范围 |
4. 风险概览
GET /api/v1/risk/overview
请求参数:无。
响应示例:
{
"data": {
"total": 12,
"levels": {
"高风险": 3,
"中风险": 4,
"低风险": 5
},
"pending": 7,
"overdue": 2,
"high_priority": []
},
"meta": {
"trace_id": "trace-id"
}
}
字段说明:
| 字段 | 说明 |
|---|---|
total |
当前未闭环预警总数,不是今日新增数 |
levels |
未闭环预警等级分布 |
pending |
状态为待处理的未闭环预警数 |
overdue |
已超过 due_at 的未闭环预警数 |
high_priority |
最多 3 条重点高风险预警 |
5. 预警队列
GET /api/v1/risk/alerts
查询参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
keyword |
string | 否 | 预警编号、类型、摘要、客户或姓名关键词 |
customer_no |
string | 否 | 业务客户编号 |
product_code |
string | 否 | 产品代码 |
product_name |
string | 否 | 产品名称模糊匹配 |
risk_level |
string | 否 | 高、中、低 |
rule_code |
string | 否 | RW-003 等规则代码 |
start_time |
datetime | 否 | 创建时间起 |
end_time |
datetime | 否 | 创建时间止 |
cursor |
string | 否 | 分页游标 |
limit |
integer | 否 | 1-10,默认 10 |
默认只返回未闭环预警,排序为高风险、中风险、低风险,同等级按创建时间倒序。
data 元素字段:
| 字段 | 说明 |
|---|---|
alert_no |
预警编号 |
customer_id |
客户内部 ID,字符串 |
customer_no |
业务客户编号 |
customer_name |
脱敏客户姓名 |
product_code |
产品代码 |
product_name |
产品名称 |
alert_type |
预警类型 |
risk_level |
风险等级 |
rule_codes |
命中规则数组 |
evidence_summary |
证据摘要 |
evidence_snapshot |
结构化证据快照 |
priority_score |
优先级分数 |
event_status |
事件状态 |
status |
处置状态 |
ack_status |
确认状态 |
ack_at |
确认时间 |
due_at |
处理时限 |
is_escalated |
是否升级 |
escalated_at |
升级时间 |
evidence_archived |
是否已归档证据 |
close_reason |
误报关闭原因 |
created_at |
创建时间 |
updated_at |
更新时间 |
6. 预警详情
GET /api/v1/risk/alerts/{alert_no}
路径参数:
alert_no:1-64 位字母、数字、下划线或连字符。
响应 data 顶层字段:
| 字段 | 说明 |
|---|---|
alert |
预警主体,字段与预警队列元素一致 |
customer |
客户脱敏信息 |
transaction |
关联交易原始只读字段 |
product |
关联产品原始只读字段 |
work_order |
关联工单原始只读字段 |
capital_flows |
资金流水列表 |
holdings |
持仓列表 |
login_records |
登录记录列表 |
evidence_snapshot |
扫规则形成的证据快照和归档信息 |
evidence_truncated |
被截断的证据类型数组 |
customer 字段:
| 字段 | 说明 |
|---|---|
customer_id |
业务客户编号 |
customer_no |
业务客户编号 |
name |
脱敏姓名 |
birth_date |
出生日期 |
occupation |
职业 |
mobile_masked |
脱敏手机号 |
investor_type |
风险承受等级 |
investment_horizon |
投资期限 |
trading_frequency |
交易频率 |
total_asset |
总资产 |
behavior_score |
行为分 |
risk_tags |
风险标签 |
updated_at |
更新时间 |
7. 手动规则扫描
POST /api/v1/risk/alerts/scan
请求头:
Idempotency-Key: <必填>
请求体:
{}
成功响应:
{
"data": {
"message": "规则扫描完成",
"created_count": 5,
"high_risk_count": 3,
"notification_count": 6,
"notification_failure": "可选,通知记录创建失败原因"
},
"meta": {
"trace_id": "trace-id"
}
}
规则:
- 与定时扫描互斥。
- 高风险预警会创建站内通知和邮件通知。
- 邮件发送失败不回滚预警。
notification_failure只代表通知记录创建失败。- 邮件真实状态通过通知记录查询。
- 手动扫描会等待高风险邮件发送结果,前端建议将该接口超时设置为不少于 60 秒。
8. 人工处置接口
以下接口均需要 risk:alert:write 和 Idempotency-Key。
8.1 确认接收
POST /api/v1/risk/alerts/{alert_no}/acknowledgements
请求体:
{}
前置条件:状态为待处理,且尚未确认。
8.2 进入调查
POST /api/v1/risk/alerts/{alert_no}/investigations
请求体:
{}
前置条件:已确认,且状态为待处理。
8.3 关闭误报
POST /api/v1/risk/alerts/{alert_no}/exclusions
请求体:
{
"reason": "误报理由,1-500 字"
}
前置条件:已确认,且当前未闭环。
8.4 完成结案
POST /api/v1/risk/alerts/{alert_no}/resolutions
请求体:
{
"resolution": "处置结论,1-500 字"
}
前置条件:已确认,且状态为调查中。
结案后按风险等级更新行为分。
8.5 升级处理
POST /api/v1/risk/alerts/{alert_no}/escalations
请求体:
{
"reason": "升级理由,1-500 字"
}
前置条件:已确认、未闭环且尚未升级。
8.6 人工处置通用响应
{
"data": {
"alert_no": "ALERT-001",
"status": "调查中",
"ack_status": "已确认",
"alert_level": "高",
"handle_result": null,
"closed_at": null
},
"meta": {
"trace_id": "trace-id"
}
}
完成结案额外返回:
behavior_score_beforebehavior_score_deductionbehavior_score_after
升级处理额外返回:
is_escalatedescalated_atescalation_reason
9. 证据归档
POST /api/v1/risk/alerts/{alert_no}/evidence
请求类型:multipart/form-data
表单字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
evidence_file |
file | 是 | 待归档文件 |
支持扩展名:
.jpg .jpeg .png .webp .pdf .doc .docx
.xls .xlsx .ppt .pptx .txt
约束:
- 单文件默认不超过 10 MB。
- 只有已确认且状态为调查中的预警可以归档。
- 一笔预警只能归档一次,不能覆盖。
- 该接口不要求
Idempotency-Key,通过“一预警一文件”保证唯一性。
响应:
{
"data": {
"alert_no": "ALERT-001",
"evidence_archived": true,
"stored_name": "ALERT-001.pdf",
"file_size": 102400
},
"meta": {
"trace_id": "trace-id"
}
}
10. 八类证据查询
GET /api/v1/risk/evidence/{source}
source 可选值:
| source | 数据 |
|---|---|
customers |
客户及行为分 |
products |
产品 |
transactions |
交易 |
capital_flows |
资金流水 |
holdings |
持仓 |
login_records |
登录记录 |
alerts |
全部预警,包括已闭环 |
notifications |
通知记录 |
通用查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
keyword |
string | 关键词 |
behavior_level |
string | 仅客户证据使用 |
send_status |
string | 仅通知证据使用 |
start_time |
datetime | 开始时间 |
end_time |
datetime | 结束时间 |
cursor |
string | 分页游标 |
limit |
integer | 1-10,默认 10 |
10.1 customers
返回字段:
customer_idcustomer_nousernamenameageoccupationmobile_maskedtotal_assetcustomer_tierrisk_levelrisk_scoreassessment_dateassessment_valid_untilassessment_expiredbehavior_scorerisk_tagsopened_atstatus
10.2 products
返回 fin_product 表字段,包含:
idproduct_codeproduct_nameexchange_codeproduct_categoryrisk_levelcurrencymin_amountstatus
10.3 transactions
返回字段:
transaction_nocustomer_noproduct_codeproduct_nametransaction_typeamountchanneltrade_statusrisk_disclosure_signedsecond_confirmationrecording_idwork_order_noconfirmed_atexecuted_at
10.4 capital_flows
返回字段:
flow_nocustomer_noflow_typeamountstatussettled_atoccurred_atsource_typematch_status
10.5 holdings
返回字段:
customer_noproduct_codeproduct_namesharescost_amountcurrent_valueprofit_lossholding_daysholding_ratio
10.6 login_records
返回字段:
idcustomer_nologin_atlogin_resultip_regiondevice_idis_common_devicefailure_reason
10.7 alerts
返回全部预警,包括未闭环和已闭环,字段与预警队列一致。
10.8 notifications
返回字段:
notification_idnotification_noalert_nocustomer_nochanneltitlesend_statusreceiver_emailsend_time
11. 通知记录
GET /api/v1/risk/notifications
查询参数:
| 参数 | 类型 | 说明 |
|---|---|---|
keyword |
string | 通知编号、预警编号、标题、状态或邮箱 |
send_status |
string | 发送状态 |
start_time |
datetime | 创建时间起 |
end_time |
datetime | 创建时间止 |
cursor |
string | 分页游标 |
limit |
integer | 1-10,默认 10 |
发送状态:
| 状态 | 说明 |
|---|---|
待发送 |
已创建邮件记录,尚未完成发送 |
已发送 |
SMTP 发送成功 |
发送失败 |
SMTP 发送失败 |
未启用 |
邮件功能未启用 |
12. 风险日报
12.1 生成结构化日报
POST /api/v1/risk/daily-report
请求体:
{
"report_date": "2026-09-13"
}
report_date 可省略,省略时使用当前北京时间日期。
主要响应字段:
| 字段 | 说明 |
|---|---|
type |
日报类型 |
report_date |
报表日期 |
generated_at |
生成时间,北京时间文本 |
data_truncated |
是否因查询上限被截断 |
daily_alert_count |
当日预警数量 |
level_distribution |
等级分布 |
key_risk_events |
重点风险事件 |
unresolved_items |
所有历史未闭环事项 |
false_positive_statistics |
误报统计 |
type_distribution |
类型分布 |
disposition_results |
处置结果 |
rule_effectiveness |
规则效果 |
optimization_suggestions |
优化建议 |
source |
模型 或 规则模板 |
prompt_version |
提示词版本 |
content |
渲染后的九段式日报文本 |
12.2 流式生成日报
POST /api/v1/risk/daily-report/stream
请求头:
Accept: text/event-stream
Content-Type: application/json
请求体与结构化日报相同。
SSE 事件:
| 事件 | 说明 |
|---|---|
start |
开始生成 |
progress |
阶段进度 |
replace |
替换当前日报正文 |
done |
最终结果,包含完整 report |
12.3 发送日报邮件
POST /api/v1/risk/daily-report/mail
请求体:
{
"recipients": ["risk@example.com"],
"subject": "风控日报",
"content": "九段式日报正文"
}
约束:
- 收件人 1-10 个。
- 收件人自动去重并校验格式。
- 主题最长 128 字。
- 正文最长 20000 字。
- 需要
risk:report:mail。
响应状态:
| 状态 | 说明 |
|---|---|
sent |
已发送 |
disabled |
日报邮件未启用 |
dry_run |
dry-run,未连接 SMTP |
configuration_error |
SMTP 配置不完整 |
13. 奶龙风控智能助手
风控 Agent 不单独定义业务 Controller,统一使用主项目 Agent Run 接口。
13.1 创建运行
POST /api/v1/agent-runs
请求体:
{
"agent_type": "risk",
"message": "查询当前高风险预警",
"session_id": "session-uuid",
"idempotency_key": "16-128位ASCII字符串"
}
成功返回 202:
{
"data": {
"run_id": "run-uuid",
"trace_id": "trace-id",
"status": "queued",
"status_url": "/api/v1/agent-runs/run-uuid",
"events_url": "/api/v1/agent-runs/run-uuid/events"
},
"meta": {
"trace_id": "trace-id"
}
}
13.2 查询运行
GET /api/v1/agent-runs/{run_id}
主要字段:
run_idtrace_idstatusagent_typesession_idresulterror_codecreated_atcompleted_at
13.3 订阅 SSE
GET /api/v1/agent-runs/{run_id}/events
请求头:
Accept: text/event-stream
事件类型:
starttoolsdeltareplacedoneerror
13.4 Agent 工具边界
允许工具:
| 工具 | 用途 |
|---|---|
get_risk_overview |
查询风险概览 |
search_risk_alerts |
查询预警列表 |
get_alert_evidence |
查询指定预警证据 |
禁止能力:
- 确认、调查、关闭、解决或升级预警。
- 修改客户、交易、资金、持仓和产品事实。
- 绕过权限和数据范围。
- 在未取得完整数据时声称已经覆盖全部数据。
13.5 会话历史
- 同一个
session_id表示同一场对话。 - Worker 会从 MySQL 读取该会话最近 10 轮消息,并在系统提示和当前问题之间传给风险 Agent。
- 通用风险问答与预警上下文使用不同
session_id。 - 刷新页面后前端会创建新
session_id,当前不承诺跨刷新恢复上下文。 - 历史消息只用于理解指代,不能作为本轮工具调用或处置指令的依据。
14. 状态和枚举
14.1 预警等级
| 值 | 展示 |
|---|---|
| 高 | 高风险 |
| 中 | 中风险 |
| 低 | 低风险 |
14.2 预警状态
| 值 | 是否未闭环 |
|---|---|
| 待处理 | 是 |
| 调查中 | 是 |
| 已排除 | 否 |
| 已结案 | 否 |
14.3 确认状态
未确认已确认
14.4 通知渠道
站内提醒邮件
14.5 行为分筛选
| 值 | 范围 |
|---|---|
normal |
16-20 |
slight |
11-15 |
attention |
6-10 |
high |
1-5 |
immediate |
0 |
15. 主项目接入注意事项
- 路由需要通过主项目统一注册
/api/v1/risk。 - 鉴权、数据范围、限流、幂等、错误信封和 SSE 协商必须复用主项目公共能力。
- 风控查询必须携带客户端
data_scope和客户归属,不能只依赖前端过滤。 - 手动扫描需要
Idempotency-Key。 - 证据上传使用
multipart/form-data,不要求幂等键。 - 高风险预警邮件由后端配置控制,当前只支持一个收件人。
- 高风险预警邮件状态通过通知接口查询,不新增独立邮件状态接口。
- 定时扫描不是 HTTP 接口,正式接入需要统一 Worker 或部署编排。
- 日报流式接口必须使用 SSE,并使用
Accept: text/event-stream。 - Agent 必须使用主项目
/api/v1/agent-runs,不能新增风控专用 Agent Controller。