平台级应用:认证对接
面向上层应用开发者的 M2M API 密钥接入指南,涵盖凭证创建、Token 流程和用户程序化创建
API 密钥颁发(M2M)
Knodo 提供机器对机器(M2M)API 密钥机制,允许上层应用以编程方式访问 Knodo 的业务 API。适用于企业内部系统集成、自动化工作流、批量数据处理等场景。
概述
M2M API 密钥采用 OAuth 2.0 风格的两步 Token 流程:
- App Token:应用通过 Client Credentials 获取不透明 App Token
- User JWT:通过 Token Exchange 将 App Token 换取用户级 JWT,用于调用业务 API
┌──────────┐ Client Credentials ┌──────────┐
│ 上层应用 │ ──────────────────────────→ │ Knodo API │
│ │ ←── App Token (opaque) ─── │ │
│ │ Token Exchange │ │
│ │ ──────────────────────────→ │ │
│ │ ←── User JWT (RS256) ───── │ │
│ │ Business API (JWT) │ │
│ │ ──────────────────────────→ │ │
└──────────┘ ←──── Response ──────────── └──────────┘前置条件
- 组织管理员权限
- 组织内已有成员(Token Exchange 需要匹配到组织成员)
创建 API 凭证
创建步骤
- 进入组织设置 > 设置,找到【API 密钥】卡片
- 点击"创建凭证"按钮
- 填写凭证信息:
| 字段 | 说明 | 必填 |
|---|---|---|
| 名称 | 凭证的显示名称,便于识别用途 | ✅ |
| 描述 | 凭证用途说明 | ❌ |
| 来源 IP 白名单 | 允许调用 API 的 IP 地址或 CIDR 段 | ✅ |
- 点击"创建"
- 立即保存 Client ID 和 Client Secret(Secret 仅创建时展示一次)

凭证管理
创建后可以在组织设置 > 设置的【API 密钥】卡片中:
- 查看详情:点击凭证行查看 Client ID(Secret 创建后不可再次查看)
- 更新信息:修改凭证名称和描述(PATCH 语义)
- 吊销凭证:输入凭证名称确认后吊销(吊销后所有关联 Token 立即失效,不可恢复)
限制
| 限制项 | 默认值 |
|---|---|
| 每组织最大凭证数 | 10 |
| App Token 有效期 | 1 小时 |
| User JWT 有效期 | 1 小时 |
接入流程
第一步:获取 App Token
使用 Client Credentials Flow 获取 App Token。支持两种传参方式:
方式一:请求体传参(推荐)
curl -X POST https://your-knodo-domain/api/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "knodo_client_xxxx",
"client_secret": "knodo_sec_xxxx"
}'方式二:Basic Auth 头传参
将 client_id:client_secret 进行 Base64 编码后放入 Authorization 头:
curl -X POST https://your-knodo-domain/api/v1/oauth/token \
-H "Authorization: Basic $(echo -n 'knodo_client_xxxx:knodo_sec_xxxx' | base64)" \
-H "Content-Type: application/json" \
-d '{"grant_type": "client_credentials"}'💡 如果请求体中已包含
client_id和client_secret,则 Basic Auth 头会被忽略。两种方式不可混合使用(例如 body 中只传client_id,头中传client_secret是不支持的)。
响应:
{
"code": "SUCCESS",
"data": {
"access_token": "eyJ...(opaque token)",
"token_type": "app_bearer",
"expires_in": 3600
}
}⚠️ App Token 是不透明 Token,不能直接调用业务 API,仅用于第二步的 Token Exchange。
第二步:换取用户级 JWT
通过 Token Exchange 将 App Token 换取可以调用业务 API 的用户级 JWT。需要提供一个"身份锚点"来识别目标用户。
请求示例:
curl -X POST https://your-knodo-domain/api/v1/oauth/user-token \
-H "Content-Type: application/json" \
-d '{
"access_token": "<app_token>",
"subject_token": "<身份锚点值>",
"subject_token_type": "dingtalk_user_id"
}'响应:
{
"code": "SUCCESS",
"data": {
"access_token": "eyJ...(RS256 JWT)",
"token_type": "Bearer",
"expires_in": 3600
}
}第三步:调用业务 API
使用 User JWT 作为 Bearer Token 调用任意业务 API:
curl https://your-knodo-domain/api/v1/workspaces \
-H "Authorization: Bearer <user_jwt>"身份锚点类型
Token Exchange 需要通过 subject_token_type 指定用户身份的匹配方式:
| subject_token_type | 说明 | 匹配字段 |
|---|---|---|
dingtalk_user_id | 钉钉用户 ID | User.dingtalkUserId |
feishu_user_id | 飞书用户 ID | User.feishuUserId |
wecom_user_id | 企微用户 ID | User.wecomUserId |
email | 邮箱地址 | User.email |
要求:匹配到的用户必须属于凭证所在的组织。
用户程序化创建
如果目标用户尚未在 Knodo 中注册,上层应用可以通过 API 自动创建用户并加入组织。
单个创建
请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
email | string | ✅ | 用户邮箱,同时作为匹配已有用户的唯一标识 |
name | string | ❌ | 用户显示名称。新建用户时不传则自动取邮箱 @ 前的部分作为名称 |
dingtalk_user_id | string | ❌ | 钉钉用户 ID(身份锚点) |
feishu_user_id | string | ❌ | 飞书用户 ID(身份锚点) |
wecom_user_id | string | ❌ | 企微用户 ID(身份锚点) |
avatar_url | string | ❌ | 用户头像 URL |
curl -X POST https://your-knodo-domain/api/v1/api-keys/users/provision \
-H "Authorization: Bearer <app_token>" \
-H "Content-Type: application/json" \
-d '{
"email": "zhangsan@company.com",
"name": "张三",
"dingtalk_user_id": "dingtalk_12345",
"feishu_user_id": "feishu_67890"
}'行为:
- 如果用户已存在(按邮箱匹配),则更新身份锚点信息;若传入的身份锚点已绑定到其他用户,返回 409 冲突
- 如果用户不存在,则创建新用户并自动加入凭证所在组织(角色为成员);若组织成员数已达套餐上限,返回 403
seat_limit_exceeded,需升级套餐或增购席位后再试
响应:
{
"code": "SUCCESS",
"data": {
"userId": "usr_xxxx",
"organizationMemberId": "om_xxxx",
"action": "created"
}
}
action字段标识本次操作结果:created(新用户)或updated(已存在,更新了身份锚点)。
批量创建
请求体为 users 数组,数组中每个元素的字段与单个创建相同(仅 email 必填)。单次最多支持 100 个用户。
curl -X POST https://your-knodo-domain/api/v1/api-keys/users/provision/batch \
-H "Authorization: Bearer <app_token>" \
-H "Content-Type: application/json" \
-d '{
"users": [
{"email": "user1@company.com", "name": "用户一", "dingtalk_user_id": "dt_001"},
{"email": "user2@company.com", "name": "用户二", "wecom_user_id": "wx_002"}
]
}'批量创建时单个用户失败不影响其他用户处理,响应中会标记每个用户的处理结果。
响应:
{
"code": "SUCCESS",
"data": {
"total": 3,
"created": 2,
"updated": 0,
"failed": 1,
"results": [
{"email": "user1@company.com", "status": "created", "userId": "usr_xxx"},
{"email": "user2@company.com", "status": "created", "userId": "usr_yyy"},
{"email": "bad-email", "status": "failed", "error": "invalid email format"}
]
}
}安全说明
凭证安全
- Client Secret 仅创建时展示一次,请立即安全保存
- 支持 IP 白名单限制调用来源
- 凭证吊销后所有 Token 立即失效
频率限制
以下为默认值,管理员可通过系统配置实时调整。
| 端点 | 限制维度 | 默认限制 |
|---|---|---|
/oauth/token、/oauth/user-token | 每个来源 IP | 10 次/分钟 |
| 业务 API(M2M JWT) | 每个凭证 | 100 次/分钟 |
错误码
所有错误响应遵循统一格式,错误详情位于 data.error 和 data.error_description 字段:
{
"code": "FAILED",
"message": "Client authentication failed",
"data": {
"error": "invalid_client",
"error_description": "Client ID 或 Secret 不正确"
}
}| 错误码 | HTTP 状态码 | 说明 |
|---|---|---|
invalid_client | 401 | Client ID 或 Secret 错误(统一提示,不区分原因) |
invalid_token | 401 | App Token 无效或已过期 |
user_not_found | 404 | 身份锚点未匹配到用户 |
user_not_in_organization | 403 | 匹配到的用户不属于凭证所在组织 |
access_denied | 403 | 请求 IP 不在白名单中 |
seat_limit_exceeded | 403 | 组织成员数已达套餐上限,需升级套餐或增购席位 |
too_many_requests | 429 | 频率限制超限,响应中包含 data.retry_after(秒)表示重试等待时间 |
典型场景
场景一:企业 HR 系统同步员工到 Knodo
- HR 系统创建 API 凭证,配置服务器 IP 白名单
- 使用批量用户创建接口同步员工数据
- 通过 Token Exchange 获取管理员 JWT,为员工创建工作空间
场景二:自动化日报生成
- 创建 API 凭证
- 通过 Token Exchange 获取指定用户的 JWT
- 调用工作空间 API 读取数据并生成日报
场景三:CI/CD 集成
- 创建专用 API 凭证,限制 CI 服务器 IP
- 在 Pipeline 中获取 App Token → Token Exchange → 调用业务 API