CZL Connect 接入文档

本文档将指导您如何将CZL Connect集成到您的应用中。

如果您有任何问题,请随时在论坛留言
复制提示词发送给 AI,即可自动编写应用级 API代码

应用级 API

CZL Connect 提供一组面向接入方后端的"应用级 API",允许应用所有者用专属凭证调用 CZL Connect 管理本应用的用户。与 OAuth2 / OIDC 用户令牌不同,本 API 不依赖任何终端用户登录态,直接基于 Authorization: Bearer <api-key> 鉴权。

适用场景

  • 接入方运营后台展示本应用用户列表、搜索、分页
  • 接入方需要程序化调整某个用户的 groups 分组
  • 接入方需要踢人下线 (撤销其对本应用的全部 OAuth2 token)
  • 接入方拉取本应用授权事件流做增量数据同步
  • 接入方监控本应用授权次数 / 活跃用户 / MAU 等运营指标

与 OAuth2 用户令牌的区别

维度OAuth2 access token应用级 API key
代表的身份某个具体用户整个应用 (作为客户端)
来源用户在浏览器走授权码流程在应用后台手动创建 / 轮换
默认权限拿到的用户可见数据应用名下所有用户的管理操作
跨用户不能,仅限自己的 userinfo可以,只要在 scope 范围内
跨应用不能不能 (一 key 绑一 App)
适用调用方用户的浏览器 / App接入方的服务端进程

不要把应用级 API key 下放给浏览器或终端 App 使用,它本质是"上帝模式"的密钥,任何持有者都能管理整个应用的用户。

凭证管理

进入应用详情页 → "API 接入" Tab,可以完成以下操作:

操作描述需要确认
新建凭证选择 scope 后生成,明文只在创建瞬间返回一次,务必立即复制保存通行密钥
轮换凭证生成新 key,旧 key 进入 24 小时宽限期,期满自动停用通行密钥
立即吊销跳过宽限期,凭证立刻停用通行密钥
删除凭证从列表移除,不可恢复通行密钥

凭证明文格式: czlc_live_<32 字符 base62 后缀>,数据库只存 SHA-256 hash 与前 12 个字符的明文前缀,后端无法反查完整凭证。

推荐的轮换流程

  1. 在前端点击"轮换",拿到新明文
  2. 把新明文部署到生产环境的配置 (环境变量 / 密钥管理)
  3. 等待生产环境实际开始使用新 key (可在凭证列表看到 LastUsedAt 更新)
  4. 24 小时内若一切正常,旧 key 自动过期,无需手动操作
  5. 若希望提前清退旧 key,可对旧 key 点击"立即吊销"

鉴权

请求头:

Authorization: Bearer czlc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

凭证验证失败返回 401,响应体:

{
  "error": "invalid_api_key",
  "message": "无效或已失效的 API 凭证"
}

凭证有效但缺少所需 scope 返回 403:

{
  "error": "insufficient_scope",
  "message": "凭证缺少所需 scope",
  "required_any_of": ["user:read"],
  "granted_scopes": ["stats:read"]
}

Scope 列表

Scope涵盖端点
user:readGET /users, GET /users/:userId, GET /events
user:writePATCH /users/:userId (修改 enabled)
group:writePATCH /users/:userId (修改 group)
stats:readGET /stats
relation:revokePOST /users/:userId/revoke

GET /meGET /groups 不需要任何 scope,只要凭证本身有效即可调用。

PATCH /users/:userId 支持同时传 groupenabled,此时分别要求 group:writeuser:write,缺一即被 403 拒绝。

限流

  • 限流单位: 单个 App,不区分凭证 (同一 App 下所有 key 共享一个桶)
  • 默认配额: 600 次/分钟
  • 响应头: X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset / Retry-After
  • 超限返回 429:
{
  "error": "rate_limited",
  "message": "请求过于频繁",
  "retry_after": 23
}

API 端点

所有端点前缀: https://connect.czl.net/api/v1/app

URL 中不出现 appID,因为凭证已绑定唯一 App,服务端从凭证反查;这也避免接入方误填别人的 App ID。

GET /me

返回当前 key 绑定的 App 元信息 + 凭证 scopes。常用于接入方启动时做"凭证自检"。

请求示例:

curl -H "Authorization: Bearer czlc_live_xxx" \
  https://connect.czl.net/api/v1/app/me

响应:

{
  "app": {
    "id": 42,
    "name": "我的应用",
    "description": "...",
    "homeUrl": "https://app.example.com",
    "logo": "https://...",
    "enabled": true,
    "isPublic": false,
    "createdAt": "2026-05-01T08:00:00+08:00"
  },
  "apiKey": {
    "id": 7,
    "name": "prod backend",
    "keyPrefix": "czlc_live_a3",
    "scopes": ["user:read", "user:write", "group:write"],
    "status": "active",
    "lastUsedAt": "2026-05-18T10:23:45+08:00",
    "createdAt": "2026-04-20T11:30:00+08:00"
  }
}

GET /users

列出本 App 用户,支持分页和过滤。

Query 参数:

名称类型默认说明
pageint1页码,从 1 开始
pageSizeint20每页条数,上限 100
keywordstring-模糊匹配 username / email
groupstring-精确匹配 group,例如 admin / t3
enabledtrue/false-按启停状态过滤,不传表示不过滤

响应:

{
  "items": [
    {
      "userId": "1001",
      "username": "alice",
      "email": "alice@example.com",
      "nickname": "",
      "avatar": "https://...",
      "emailVerified": true,
      "group": "t2",
      "enabled": true,
      "authCount": 42,
      "firstAuthAt": "2026-01-15T09:00:00+08:00",
      "lastAuthAt": "2026-05-17T22:01:00+08:00",
      "lastLoginAt": "2026-05-17T22:01:00+08:00",
      "createdAt": "2026-01-15T09:00:00+08:00"
    }
  ],
  "total": 1234,
  "page": 1,
  "pageSize": 20
}

GET /users/:userId

获取单个用户在本 App 中的详情,字段同 /users 单条。userId 是用户在 CZL Connect 内部的数字 ID,可从 /users 列表或 OAuth2 userinfo 中获取。

用户不存在或未授权本 App 时返回 404:

{
  "error": "user_not_found",
  "message": "该用户不存在或未授权此应用"
}

PATCH /users/:userId

更新用户在本 App 中的 groupenabled 状态。

请求体 (两个字段都可选,至少提供一个):

{
  "group": "t3",
  "enabled": true
}

group 合法值: admin / viewer / t0 ~ t5,详见 GET /groups

enabledfalse 时,会同时撤销该用户在本 App 的所有 OAuth2 token (强制下线)。响应返回更新后的用户视图。

POST /users/:userId/revoke

撤销该用户对本 App 的全部 OAuth2 token,即"踢下线"。不会删除用户在本 App 的关系记录;用户下次访问本 App 时仍需走授权流程重新登录。

响应:

{
  "revoked": true,
  "revokedTokens": 3
}

GET /stats

本 App 的聚合统计。响应:

{
  "totalUsers": 1234,
  "totalAuths": 56789,
  "activeUsers30d": 432,
  "newUsers30d": 87,
  "dailyAuthCounts": [
    { "date": "2026-05-17", "count": 234 },
    { "date": "2026-05-16", "count": 189 }
  ]
}

GET /events

本 App 的授权事件流,按时间倒序。适合接入方做增量数据同步: 持续轮询并记录最后一次拉到的 idcreatedAt

Query 参数:

名称类型默认说明
limitint50单次最大返回数,上限 200
beforeRFC3339-仅返回早于该时间的事件
eventTypestring-按事件类型过滤,例如 authorization_granted

响应:

{
  "items": [
    {
      "id": 99837,
      "eventType": "authorization_granted",
      "protocol": "oauth2",
      "status": "success",
      "userId": "1001",
      "scope": "openid profile email",
      "description": "",
      "createdAt": "2026-05-17T22:01:00+08:00"
    }
  ],
  "limit": 50
}

事件类型常见取值: authorization_granted / authorization_revoked / code_issued / token_issued / token_refreshed / token_revoked

GET /groups

返回所有可用 group + 层级展开说明。可用于接入方渲染下拉。

响应:

{
  "items": [
    {
      "code": "admin",
      "description": "管理员,可在本应用内管理用户、查看统计",
      "impliedGroups": ["t0", "t1", "t2", "t3", "t4", "t5", "viewer", "admin"]
    },
    {
      "code": "t3",
      "description": "等级 3",
      "impliedGroups": ["t0", "t1", "t2", "t3"]
    }
  ],
  "note": "t0-t5 按数字递增继承低等级 group;admin 独立,拥有全部权限;viewer 独立,仅可查看"
}

错误响应统一格式

所有 4xx / 5xx 响应都遵循:

{
  "error": "<machine_readable_code>",
  "message": "<human readable text>"
}

常见 error 取值:

codeHTTP含义
missing_api_key401缺少 Authorization 头
invalid_api_key401凭证格式错误 / 已失效 / 不存在
insufficient_scope403凭证有效但缺少所需 scope
rate_limited429触发限流
user_not_found404用户不存在或未授权本 App
invalid_body400请求体不合法
empty_body400PATCH 时没提供任何可更新字段
invalid_user_id400:userId 参数无效
query_failed500内部查询异常
context_missing500内部上下文缺失 (通常意味着部署问题)

调用示例

cURL

# 拉用户列表
curl -H "Authorization: Bearer czlc_live_xxx" \
  "https://connect.czl.net/api/v1/app/users?page=1&pageSize=20"

# 修改 group
curl -X PATCH -H "Authorization: Bearer czlc_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"group":"t3"}' \
  https://connect.czl.net/api/v1/app/users/1001

# 踢人下线
curl -X POST -H "Authorization: Bearer czlc_live_xxx" \
  https://connect.czl.net/api/v1/app/users/1001/revoke

Go

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

const apiKey = "czlc_live_xxx"

func listUsers() {
    req, _ := http.NewRequest("GET", "https://connect.czl.net/api/v1/app/users?pageSize=50", nil)
    req.Header.Set("Authorization", "Bearer "+apiKey)
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))
    _ = json.RawMessage{}
}

Node.js

const API_KEY = process.env.CZL_CONNECT_API_KEY!;

async function setGroup(userId: string, group: string) {
  const r = await fetch(`https://connect.czl.net/api/v1/app/users/${userId}`, {
    method: "PATCH",
    headers: {
      "Authorization": `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ group }),
  });
  if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
  return r.json();
}

安全建议

  • 凭证只下发到服务端,不要放进前端代码 / 移动 App / 公开仓库
  • 不同环境 (生产 / 预发 / 沙箱) 使用不同凭证,便于事故时精准吊销
  • 启用 scope 最小化: 只给必要的 scope,不要默认全选
  • 凭证泄漏怀疑时立刻"立即吊销" + 新建,不走宽限期
  • 定期 (例如季度) 主动轮换一次,降低长期暴露风险
  • 监控接入方后端日志,关注异常的 429 / 403 响应