CGL SCRM / api
REST API
对外开放 API + MCP 端点
这是什么
一句话:让程序(而不是人)来跟这套系统打交道。
老系统完全没有这个能力——想拿数据只能在后台页面上人肉翻页、点导出。 我们新开了一组接口,把线索、活动报名、问卷、二维码、统计 都变成机器能直接读写的格式(JSON)。
它能用来干什么:
- 让公司内部的 AI 助手(Aily 平台)自己去取数、做二次加工;
- 跑定时任务,比如每天早上把线索同步到另一个系统;
- 将来做小程序、大屏看板时,直接拿这组接口当数据源。
这块是「额外新增」,不碰原来的东西。
所有接口都收在
/api/v1/ 这个前缀下面,
和后台页面(/manager/)、客户看到的页面(/video/)
互不干扰。所以哪怕这些接口将来全改了,老页面也不受影响。
怎么证明「你是谁」
一共支持三种方式。每一种都是给不同的人用的,不要混。
API 钥匙
给程序和 AI 用的。放在请求头里:
或者
每把钥匙带一组权限,只能干被允许的事。
X-API-Key: cgl_…或者
Authorization: Bearer cgl_…。每把钥匙带一组权限,只能干被允许的事。
后台登录会话
同事在浏览器里登录后自动带的凭证。
后台首页那块「实时看板」走的就是这条路, 这样数据和页面不会出现两个来源。
后台首页那块「实时看板」走的就是这条路, 这样数据和页面不会出现两个来源。
不用登录
少数几个刻意开放的:客户报名的页面、二维码图片、微信回调、体检地址。
完整清单在「安全模型」那一页,逐条列出来并说明为什么。
权限分得有多细(11 档)
钥匙不是「要么全能、要么不能」,而是按业务动作切开的。 给市场部同事发钥匙时,通常只给「看」的那几档。
| 权限 | 允许做什么 | 用在多少个接口上 |
|---|---|---|
| event:read | 看活动和报名名单 | 3 个 |
| event:write | 办活动、改活动、审报名、签到 | 3 个 |
| lead:read | 看线索(手机号、邮箱会打码) | 4 个 |
| lead:read_pii | 看线索的真实手机号和邮箱(不打码)—— 单独一个权限,不轻易给 | 0 个 |
| lead:write | 改线索:加备注、跟进行为、改状态、打标签、合并重复 | 5 个 |
| qrcode:read | 看二维码台账 | 2 个 |
| qrcode:write | 生成新二维码 | 2 个 |
| stats:read | 看统计报表 | 8 个 |
| survey:read | 看问卷和答卷 | 3 个 |
| survey:write | 建问卷、改题目、提交答卷 | 1 个 |
| token:admin | 管理 API 钥匙本身(签发 / 吊销)—— 只给系统管理员 | 0 个 |
手机号默认打码:接口返回的线索里,手机号是
138****9999 这种形式。
要看真实号码,钥匙必须额外带 lead:read_pii 这一档。
这是故意加的护栏——老系统的导出表格里手机号全是明文,转发一次就外泄一次。
全部 36 个接口
下表「需要什么」那一列是从代码里现场读出来的,不是照着代码抄的。 空着的那几条说明它们不限定具体权限,只要身份有效就行——下面单独解释。
| 方式 | 接口地址 | 处理函数 | 需要什么 | 干什么 |
|---|---|---|---|---|
| GET | /api/v1/events | api_events | event:read | 活动列表 |
| GET | /api/v1/events/{aid} | api_event_detail | event:read | 活动详情(含统计/表单字段/分享码) |
| GET | /api/v1/events/{aid}/signups | api_event_signups | event:read | 报名名单 |
| POST | /api/v1/events/{aid}/signups | api_event_signup | event:write | 代客报名(写线索 + 评分 + 归因) |
| POST | /api/v1/events/{aid}/signups/{sid}/audit | api_audit_signup | event:write | 报名审核 |
| POST | /api/v1/events/{aid}/signups/{sid}/checkin | api_checkin | event:write | 签到 |
| GET | /api/v1/health | api_health | 无需登录 | 供 Aily / 监控探活。 |
| GET | /api/v1/leads | api_leads | lead:read | 线索列表(分页 + 筛选) |
| GET | /api/v1/leads/duplicates | api_find_duplicates | lead:read | 查重(手机/邮箱/openid 三键) |
| GET | /api/v1/leads/export.csv | api_export_leads | lead:read | 导出线索 CSV。 |
| POST | /api/v1/leads/merge | api_merge_leads | lead:write | 合并重复线索(新功能) |
| GET | /api/v1/leads/{uid:int} | api_lead_detail | lead:read | 线索详情(含标签/行为/备注/归因链) |
| POST | /api/v1/leads/{uid:int}/behaviors | api_add_behavior | lead:write | 写入线索行为(自动参与评分) |
| POST | /api/v1/leads/{uid:int}/remark | api_add_remark | lead:write | 追加跟进备注 |
| POST | /api/v1/leads/{uid:int}/status | api_set_status | lead:write | 变更线索状态 |
| POST | /api/v1/leads/{uid:int}/tags | api_set_tags | lead:write | 打标签 / 取消标签 |
| GET | /api/v1/meta/scopes | api_scopes | 有效钥匙即可 | 列出可用 scope |
| GET | /api/v1/qrcodes | api_qrcodes | qrcode:read | 二维码台账(新功能:原站不落档、不可统计) |
| POST | /api/v1/qrcodes/event | api_qrcode_event | qrcode:write | 生成活动带参二维码 |
| GET | /api/v1/qrcodes/preview.png | api_qrcode_preview | qrcode:read | 内网演示 / 联调用:本地生成 PNG 直出,不产生微信归因。 |
| POST | /api/v1/qrcodes/survey | api_qrcode_survey | qrcode:write | 生成问卷带参二维码 |
| GET | /api/v1/stats/behaviors | api_stats_behaviors | stats:read | 行为分布 |
| GET | /api/v1/stats/channels | api_stats_channels | stats:read | 渠道分布 |
| GET | /api/v1/stats/funnel | api_stats_funnel | stats:read | 状态漏斗 |
| GET | /api/v1/stats/leaderboard | api_stats_leaderboard | stats:read | 顾问业绩榜 + 活动/问卷排行 |
| GET | /api/v1/stats/overview | api_stats_overview | stats:read | 总览指标(含环比) |
| GET | /api/v1/stats/recent-leads | api_stats_recent | stats:read | 最新线索(供大屏轮播) |
| GET | /api/v1/stats/today | api_stats_today | stats:read | 今日快照 |
| GET | /api/v1/stats/trend | api_stats_trend | stats:read | 新增线索 / 报名 / 答卷 趋势 |
| GET | /api/v1/surveys | api_surveys | survey:read | 问卷列表 |
| GET | /api/v1/surveys/{qid}/answers | api_survey_answers | survey:read | 答卷列表 |
| POST | /api/v1/surveys/{qid}/answers | api_survey_answer | survey:write | 提交答卷(自动评分并落线索) |
| GET | /api/v1/surveys/{qid}/schema | api_survey_schema | survey:read | 问卷结构(供 H5 / 外部表单渲染) |
| GET | /api/v1/tokens | api_tokens | 后台登录 · 管理员 | Token 列表(含归属人与签发人) |
| POST | /api/v1/tokens | api_token_create | 后台登录 · 管理员 | 按人签发。 |
| DELETE | /api/v1/tokens/{tid} | api_token_revoke | 后台登录 · 管理员 | 停用 Token(软停,记录保留) |
那几条「不需要具体权限」的
| 接口 | 为什么可以只要身份、不要具体权限 |
|---|---|
| GET /api/v1/health | 体检用的:返回服务活着、连得上数据库、现在有多少条线索。 设计上就是公开的(代码摘要里写明了「无需鉴权」)。 唯一值得斟酌的是它顺带把线索总数也报了出来; 收窄这一点会改动对外约定,属于业务决定,已经记进缺陷台账。 |
| GET /api/v1/meta/scopes | 「我手里这把钥匙有哪些权限」——拿来自己查自己。必须先通过钥匙校验,但不需要额外权限。 |
| GET/POST /api/v1/tokens DELETE /api/v1/tokens/{id} |
管理钥匙本身。走的是后台登录会话这条路——必须是登录的管理员,不能用钥匙来签发钥匙。 |
调用约定(写代码的人看)
| 列表返回什么 | 一律是 {total, page, size, pages, items}——分页信息就在同一个信封里,不用另外去猜。 |
|---|---|
| 写操作返回什么 | {"ok": true, …};失败则是 HTTP 状态码 + {"detail": "…"}。 |
| 时间格式 | ISO-8601 带时区,按北京时间给出。数据库里存的仍是世界时——全局统一,避免「差 8 小时」这类问题。 |
| 参数填错 | 直接拒绝并说清哪个参数不对。不会替你猜一个默认值然后继续跑。 |
| 字段名 | 以 docs/MODEL_REFERENCE.md 为准。比如线索里是 firstname/lastname,不是直觉上的 name。 |
一个真实例子
# 问一句:最近有哪些线索?(只看前 5 条) curl -H "X-API-Key: cgl_你的钥匙" \ "https://scrm.jxccwx.com/api/v1/leads?page=1&size=5" # 返回(手机号是打码的,因为这把钥匙没有 lead:read_pii) { "total": 11348, "page": 1, "size": 5, "pages": 2270, "items": [ { "firstname": "…", "mobile": "138****9999" } ] }
调试时可以打开 /api/docs 看自动生成的接口说明页——
不过线上是正式环境,这个页面被刻意关掉了,只有开发和测试环境能看到。