https://crm-api.mindsetech.com/internal/v1,下文完整路径均已包含此前缀。Content-Type: application/json; charset=utf-8。openapi.yaml 只包含第三方应用接口,可导入 Apifox/Postman。该文件对线上缺少响应定义的 ping 做了补齐,同时依据返回实现修正会议列表误包裹的数组层,以及 Expert.settled_at 的 nullable;其余结构保留线上契约。| Scope | 用途 |
|---|---|
| application:ping | 验证应用连通性 |
| conference:read | 查询本应用可见会议、内容、话题和公开专家 |
| client:resolve | 按已验证手机号解析客户联系人;这是单独授权的全局解析能力 |
| client:read | 按联系人 ID 或精确手机号读取姓名、公司、职位;独立授权的全局只读投影,不代表手机号身份认证 |
| registration:create | 参会报名、预约纪要及专家约访请求 |
| registration:read | 查询本应用范围内的报名、预约与我的记录 |
| registration:cancel | 取消原参会报名 |
| meeting:join | 获取有效报名联系人的入会链接 |
| meeting:write | 创建会议、修改状态、关联专家及登记参会 |
| meeting:publish | 管理应用向指定其他消费应用发布会议;还需 meeting:write |
| meeting:finance | 查询会议专家费用及登记结算 |
| user:read | 只读查询 NDB 员工基本资料(需单独显式授权) |
| user:authenticate | 验证启用员工邮箱密码,只返回基本资料,不签发或更新员工令牌;独立显式授权 |
| expert:read | 读取明确向 AI 平台公开的已发布专家资料(需单独显式授权) |
| expert:lookup | 按手机号或邮箱精确查询内部专家的姓名、公司、职位;独立全局只读权限,需管理员单独显式授权 |
X-NDB-Scope 不能扩权,权限以服务端应用配置为准。Scope 注册表中的 registration:check 当前没有独立线上路由,报名资格由报名接口校验。/catalog/ 下的内容、话题与公开专家目录按消费应用隔离,需已发布且发布时间已到。公开专家还要求内部专家未删除并开启 WECHAT_MINI_APP 公开平台;当前目录仍采用此平台条件,接入其他渠道前应确认发布配置。目录不返回内部专家联系方式、支付资料或全量专家库。/internal/v1/experts/ 使用独立 expert:read Scope 和 AI_PLATFORM 许可,共用人工确认的公开资料。来源由服务端 MEETING_WEB_APPLICATION_NAME 固定,已授权消费应用可读取该共用资料集,不能通过请求参数切换来源。只勾选微信小程序不会向AI平台公开。取消AI许可、资料下架或转草稿后,接口停止返回该专家。已下载副本不自动撤回,调用方须重新核验可见状态,并在404后停止使用和清理副本。/internal/v1/users/ 使用独立 user:read Scope,查询的是 NDB 员工账号,不是客户联系人或小程序用户。user:read、expert:read 与 expert:lookup 相互独立,均不随既有会议/目录权限自动授予。expert:read 不覆盖 expert:lookup。| Header | 内容 |
|---|---|
| X-NDB-Access-Key | 管理员提供的 AK |
| X-NDB-Timestamp | 当前 Unix 时间戳,单位秒,十进制整数;不要用毫秒 |
| X-NDB-Nonce | 每个 HTTP 请求新生成的随机值,例如去掉连字符的 UUID;最多 128 字符 |
| X-NDB-Content-SHA256 | 实际 HTTP 请求体字节的 SHA-256,小写十六进制 |
| X-NDB-Signature | 下述签名原文经 SK 做 HMAC-SHA256,小写十六进制 |
\n),第六行后不加换行:HTTP_METHOD
REQUEST_PATH
CANONICAL_QUERY_STRING
TIMESTAMP
NONCE
CONTENT_SHA256HTTP_METHOD 使用大写,例如 GET、POST。REQUEST_PATH 使用实际发送的完整路径,例如 /internal/v1/meetings/,不含域名和 ?query。是否有尾部 / 会影响签名,不能签名后改路径。建议固定使用文档中的尾斜杠形式,拒绝自动跳转。= 和 & 拼接。空格编码 %20,不是 +;~ 保留;其他如 !、'、(、)、* 编码。原始查询中的 + 会解码为空格,字面加号应发送 %2B。不要重复编码。CONTENT_SHA256 = SHA256(body_bytes).hexdigest()。无请求体时使用空字节串;其摘要固定为 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855。空请求体与 {} 的摘要不同。SIGNATURE = HMAC_SHA256(UTF8(SK), UTF8(canonical_request)).hexdigest();SK 按原字符串 UTF-8 使用,不做 Base64 解码。原始查询:b=2&a=hello+world&a=%2B&a=&keyword=%E6%96%B0%E8%83%BD%E6%BA%90
规范查询:a=&a=%2B&a=hello%20world&b=2&keyword=%E6%96%B0%E8%83%BD%E6%BA%90signature-vector.json 使用公开虚构测试密钥,包含固定时间戳、Nonce、请求体、规范原文和预期签名,可用来核对不同语言实现。固定向量只供离线测试,不可直接用于线上请求。example-secret-key-for-offline-test-only。请求体 UTF-8 文本:{"client_contact_id":2001,"message":"离线签名测试"}POST
/internal/v1/catalog/experts/4101/interview-requests/
a=&a=%2B&a=hello%20world&b=2&keyword=%E6%96%B0%E8%83%BD%E6%BA%90
1792029600
00112233445566778899aabbccddeeff
7c74527f902ac8846267cdf11fc5cd3c1e9acb78d1a5bfba91592c5738dcee93X-NDB-Signature:c5722996f60fecc17d67dd88e4c9a98279bf904675847fadd207d008bd4cb30andb_client.py(Python 3.9+ 标准库)和 ndb-client.mjs(Node.js 20+)可直接使用。两者从环境变量读取 AK/SK,禁止重定向,不自动重试。请由机密管理系统注入 NDB_ACCESS_KEY、NDB_SECRET_KEY,可选 NDB_BASE_URL 默认为生产 HTTPS 域名。不要在聊天或日志中打印密钥。python3 ndb_client.py 只调用 ping。业务调用:node ndb-client.mjs 只调用 ping。业务调用:--data-binary @body.json,必须签名该文件的完整字节,包括可能存在的末尾换行,并添加 Content-Type 及需要的 Idempotency-Key。不要使用 curl -L。page=1&page_size=20,page>=1,page_size=1–100,返回 data.items 和 data.total;报名全量列表、会议专家费用列表与轮播图返回数组,不使用分页。+08:00 的 ISO 8601 时间。其他时间字段也按 ISO 8601 读取并保留时区。小时、金额等 decimal 字段按字符串处理,避免二进制浮点误差。所有示例 ID 都是虚构值,不能直接当作生产 ID。code 为数值 200,message 可为 null、操作成功或鉴权成功,具体业务值位于 data。会议与目录业务失败 使用真实 HTTP 4xx 和字符串业务 code;ping 使用公共异常处理,鉴权失败 code 可为 authentication_failed,权限失败可为数值 403。客户端必须同时检查 HTTP 状态和 code,不要依赖 message 文案。Idempotency-Key。业务键按应用唯一,1–128 字符且首尾无空格;同一操作重试保留业务键、method、path 和 JSON 内容,时间戳与 HMAC Nonce 重新生成。不同业务操作不可共用一个键。IDEMPOTENCY_CONFLICT。原快照可能早于后续状态变化,要获取当前状态请再 GET。失败操作不占用成功业务键。网络超时或连接断开时,保留原业务键重新签名重试;不要凭超时判定业务未执行。对 4xx 先修复参数、权限或业务前置条件,避免无差别循环重试。client_contact_id 为 NDB Clients 客户联系人 ID;project_id、contract_id 由 NDB 业务人员提供或由报名服务唯一解析,应用接口没有通用项目/合同目录。/catalog/experts/{expert_id}/ 和其约访接口路径使用 PublicExpertProfile.id(公开资料 ID);列表 data.items[].id 就是该 ID。/meetings/{meeting_id}/experts/ 的请求体及结算路径 expert_id 使用 Candidates.id(内部专家 ID)。experts[].id 是内部专家 ID,而 experts[].public_profile.id 是公开资料 ID;不要互换。目录详情不提供全量内部专家档案。/internal/v1/experts/{expert_id}/ 使用公开资料 ID(列表 data.items[].id),不是内部 Candidates ID。| 编号 | 接口 | 用途 | Scope |
|---|---|---|---|
| 01 | GET /internal/v1/application-auth/ping/ | 验证应用鉴权 | application:ping |
| 02 | GET /internal/v1/catalog/content/ | 内容列表 | conference:read |
| 03 | GET /internal/v1/catalog/content/{content_id}/ | 内容详情 | conference:read |
| 04 | GET /internal/v1/catalog/experts/ | 公开专家列表 | conference:read |
| 05 | GET /internal/v1/catalog/experts/{expert_id}/ | 公开专家详情 | conference:read |
| 06 | POST /internal/v1/catalog/experts/{expert_id}/interview-requests/ | 提交专家约访请求 | registration:create |
| 07 | GET /internal/v1/catalog/topics/ | 话题列表 | conference:read |
| 08 | GET /internal/v1/catalog/topics/{topic_id}/ | 话题详情 | conference:read |
| 09 | POST /internal/v1/clients/resolve/ | 解析客户联系人 | client:resolve |
| 10 | GET /internal/v1/meetings/ | 会议列表 | conference:read |
| 11 | POST /internal/v1/meetings/ | 创建会议 | meeting:write |
| 12 | GET /internal/v1/meetings/{meeting_id}/ | 会议详情 | conference:read |
| 13 | GET /internal/v1/meetings/{meeting_id}/experts/ | 查询会议专家费用 | meeting:finance |
| 14 | POST /internal/v1/meetings/{meeting_id}/experts/ | 添加会议专家 | meeting:write |
| 15 | POST /internal/v1/meetings/{meeting_id}/experts/{expert_id}/settlement/ | 结算会议专家费用 | meeting:finance |
| 16 | GET /internal/v1/meetings/{meeting_id}/join-link/ | 获取入会链接 | meeting:join |
| 17 | GET /internal/v1/meetings/{meeting_id}/registration/ | 查询单人报名或预约 | registration:read |
| 18 | POST /internal/v1/meetings/{meeting_id}/registration/cancel/ | 取消参会报名 | registration:cancel |
| 19 | GET /internal/v1/meetings/{meeting_id}/registrations/ | 会议报名与预约列表 | registration:read |
| 20 | POST /internal/v1/meetings/{meeting_id}/registrations/ | 参会报名或预约纪要 | registration:create |
| 21 | POST /internal/v1/meetings/{meeting_id}/registrations/{client_contact_id}/attendance/ | 登记参会情况 | meeting:write |
| 22 | POST /internal/v1/meetings/{meeting_id}/status/ | 结束或取消会议 | meeting:write |
| 23 | GET /internal/v1/meetings/banners/ | 会议轮播图 | conference:read |
| 24 | GET /internal/v1/meetings/mine/ | 我的报名与预约 | registration:read |
| 25 | GET /internal/v1/users/ | 查询 NDB 员工基本资料 | user:read |
| 26 | GET /internal/v1/experts/ | 查询 AI 平台专家公开资料 | expert:read |
| 27 | GET /internal/v1/experts/{expert_id}/ | 读取 AI 平台专家公开详情 | expert:read |
| 28 | GET /internal/v1/clients/ | 精确查询客户联系人资料(目前仅生产提供) | client:read |
| 29 | GET /internal/v1/experts/lookup/ | 按手机号或邮箱精确查询专家基本资料(生产与测试均提供) | expert:lookup |
| 30 | POST /internal/v1/users/authenticate/ | 验证员工邮箱密码并返回基本资料(测试1.20.6b0起) | user:authenticate |
GET /internal/v1/application-auth/ping/application:ping。{
"code": 200,
"message": "鉴权成功",
"data": {
"application_id": 21,
"application_name": "第三方渠道测试应用",
"access_key": "ndb_example_access_key"
}
}GET /internal/v1/catalog/content/conference:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
keyword | query | string | 否 | 关键词;按对应资源的标题、简介等文本搜索。 |
page | query | integer | 否 | 页码,默认 1,最小 1。 |
page_size | query | integer | 否 | 每页数量,默认 20,范围 1–100。 |
type | query | string | 否 | 资源类型,见枚举及本节业务说明。 |
{
"data": {
"items": [
{
"id": 5001,
"meeting_id": 1001,
"meeting_title": "新能源汽车产业交流会",
"type": "minutes",
"title": "产业交流会议纪要",
"summary": "行业趋势摘要",
"body": "示例正文",
"cover_url": "https://example.com/content-cover.png",
"industry": "新能源",
"industry_id": 6001,
"tags": [
"新能源"
],
"source": "internal",
"attachments": [
{
"name": "会议纪要.pdf",
"url": "https://example.com/minutes.pdf",
"type": "application/pdf",
"size": 102400
}
],
"published_at": "2026-10-15T10:00:00+08:00"
}
],
"total": 1
},
"code": 200,
"message": null
}GET /internal/v1/catalog/content/{content_id}/conference:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
content_id | path | string | 是 | 内容 ID。 格式:"^\d+$" |
{
"data": {
"id": 5001,
"meeting_id": 1001,
"meeting_title": "新能源汽车产业交流会",
"type": "minutes",
"title": "产业交流会议纪要",
"summary": "行业趋势摘要",
"body": "示例正文",
"cover_url": "https://example.com/content-cover.png",
"industry": "新能源",
"industry_id": 6001,
"tags": [
"新能源"
],
"source": "internal",
"attachments": [
{
"name": "会议纪要.pdf",
"url": "https://example.com/minutes.pdf",
"type": "application/pdf",
"size": 102400
}
],
"published_at": "2026-10-15T10:00:00+08:00"
},
"code": 200,
"message": null
}GET /internal/v1/catalog/experts/conference:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
keyword | query | string | 否 | 关键词;按对应资源的标题、简介等文本搜索。 |
page | query | integer | 否 | 页码,默认 1,最小 1。 |
page_size | query | integer | 否 | 每页数量,默认 20,范围 1–100。 |
{
"data": {
"items": [
{
"id": 4101,
"display_name": "王先生",
"display_company": "某新能源企业",
"display_position": "技术负责人",
"display_background": "新能源技术及产业经验",
"avatar_url": "https://example.com/avatar.png",
"industry": "新能源",
"industry_id": 6001,
"tags": [
"新能源"
],
"share_topics": "技术路线与供应链",
"published_at": "2026-10-15T10:00:00+08:00",
"meetings": []
}
],
"total": 1
},
"code": 200,
"message": null
}GET /internal/v1/catalog/experts/{expert_id}/conference:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
expert_id | path | string | 是 | 目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。 格式:"^\d+$" |
{
"data": {
"id": 4101,
"display_name": "王先生",
"display_company": "某新能源企业",
"display_position": "技术负责人",
"display_background": "新能源技术及产业经验",
"avatar_url": "https://example.com/avatar.png",
"industry": "新能源",
"industry_id": 6001,
"tags": [
"新能源"
],
"share_topics": "技术路线与供应链",
"published_at": "2026-10-15T10:00:00+08:00",
"meetings": []
},
"code": 200,
"message": null
}POST /internal/v1/catalog/experts/{expert_id}/interview-requests/registration:create。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 是 | 应用内唯一的业务幂等键,1–128 字符,首尾无空格。 |
expert_id | path | string | 是 | 目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。 格式:"^\d+$" |
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
client_contact_id | body | integer | 是 | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 最小:1 |
message | body | string | 否 | 约访需求文字,最多 2000 字符;响应顶层 message 为提示文字。 最长字符数:2000 |
{
"client_contact_id": 2001,
"message": "希望交流新能源供应链趋势"
}{
"data": {
"id": 7101,
"expert_profile_id": 4101,
"client_contact_id": 2001,
"message": "希望交流新能源供应链趋势",
"status": "pending",
"created_at": "2026-10-15T10:00:00+08:00"
},
"code": 200,
"message": "操作成功"
}GET /internal/v1/catalog/topics/conference:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
keyword | query | string | 否 | 关键词;按对应资源的标题、简介等文本搜索。 |
page | query | integer | 否 | 页码,默认 1,最小 1。 |
page_size | query | integer | 否 | 每页数量,默认 20,范围 1–100。 |
{
"data": {
"items": [
{
"id": 6001,
"name": "新能源产业趋势",
"background": "行业背景",
"outline": "技术与市场",
"cover_url": "https://example.com/topic-cover.png",
"industry": "新能源",
"industry_id": 6001,
"tags": [
"新能源"
],
"published_at": "2026-10-15T10:00:00+08:00",
"meetings": [],
"contents": [],
"experts": []
}
],
"total": 1
},
"code": 200,
"message": null
}GET /internal/v1/catalog/topics/{topic_id}/conference:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
topic_id | path | string | 是 | 话题 ID。 格式:"^\d+$" |
{
"data": {
"id": 6001,
"name": "新能源产业趋势",
"background": "行业背景",
"outline": "技术与市场",
"cover_url": "https://example.com/topic-cover.png",
"industry": "新能源",
"industry_id": 6001,
"tags": [
"新能源"
],
"published_at": "2026-10-15T10:00:00+08:00",
"meetings": [],
"contents": [],
"experts": []
},
"code": 200,
"message": null
}POST /internal/v1/clients/resolve/client:resolve。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
verified_phone | body | string | 是 | 服务端已验证的手机号,可选前导 +,其后 6–20 位数字;不是手机号验证码。 格式:"^\+?[0-9]{6,20}$" |
channel | body | ChannelEnum | 是 | 当前仅支持 wechat。 枚举:["wechat"] |
{
"verified_phone": "13800000000",
"channel": "wechat"
}{
"data": {
"client_contact_id": 2001,
"requires_reauthentication": false,
"reauthentication_since": null
},
"code": 200,
"message": null
}GET /internal/v1/meetings/conference:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
date | query | string | 否 | 会议开始日期,YYYY-MM-DD;与 month 同传时叠加过滤。 |
keyword | query | string | 否 | 关键词;按对应资源的标题、简介等文本搜索。 |
month | query | string | 否 | 会议开始月份,YYYY-MM。 |
page | query | integer | 否 | 页码,默认 1,最小 1。 |
page_size | query | integer | 否 | 每页数量,默认 20,范围 1–100。 |
{
"data": {
"items": [
{
"id": 1001,
"consumer_application_id": 21,
"managed_by_application_id": 21,
"updated_by_id": null,
"project_id": 3001,
"title": "新能源汽车产业交流会",
"type": "ONLINE",
"tags": [
"新能源"
],
"industry_id": null,
"industry_name": null,
"background": "交流行业趋势",
"description": "线上专题交流",
"outline": "市场趋势与技术路线",
"background_image_url": "https://example.com/meeting-cover.png",
"experts": [],
"starts_at": "2026-10-20T14:00:00+08:00",
"ends_at": "2026-10-20T15:00:00+08:00",
"client_charge_hours": "1.0000",
"customer_charge_hours": 1.0,
"is_third_party": false,
"registration_open": true,
"status": "published",
"created_at": "2026-10-15T10:00:00+08:00",
"updated_at": "2026-10-15T10:00:00+08:00"
}
],
"total": 1
},
"code": 200,
"message": null
}POST /internal/v1/meetings/meeting:write。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 是 | 应用内唯一的业务幂等键,1–128 字符,首尾无空格。 |
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
consumer_application_id | body | integer | 否 | 消费应用 ID;指定其他应用时额外需要 meeting:publish。 最小:1 |
project_id | body | integer | 是 | NDB 项目 ID。 最小:1 |
title | body | string | 是 | 标题。 最长字符数:256 |
type | body | MeetingTypeEnum | 否 | 资源类型,见枚举及本节业务说明。 枚举:["ONLINE", "SUMMARY", "REPORT"] 默认:"ONLINE" |
tags | body | string[] | 否 | 标签数组。 |
industry_id | body | integer 或 null | 否 | NDB 行业 ID。 |
background | body | string | 否 | 背景介绍。 默认:"" |
description | body | string | 否 | 详情说明。 |
outline | body | string | 否 | 提纲。 |
background_image_url | body | string (uri) | 否 | 背景图完整 HTTP(S) URL;不可携带账号密码。 最长字符数:2048 |
join_url | body | string (uri) | 否 | 入会链接;会 议公开 DTO 不包含,只由入会接口返回。 最长字符数:2048 |
starts_at | body | string (date-time) | 是 | 会议开始时间,ISO 8601;建议显式使用 +08:00。 |
ends_at | body | string (date-time) | 是 | 会议结束时间,必须晚于 starts_at。 |
client_charge_hours | body | string (decimal) | 是 | 客户收费小时,非负十进制字符串,最多 6 位整数、4 位小数。 格式:"^-?\d{0,6}(?:\.\d{0,4})?$" |
is_third_party | body | boolean | 否 | 是否第三方会议,默认 false。 默认:false |
{
"project_id": 3001,
"title": "新能源汽车产业交流会",
"type": "ONLINE",
"tags": [
"新能源"
],
"background": "交流行业趋势",
"description": "线上专题交流",
"outline": "市场趋势与技术路线",
"background_image_url": "https://example.com/meeting-cover.png",
"join_url": "https://example.com/join/demo",
"starts_at": "2026-10-20T14:00:00+08:00",
"ends_at": "2026-10-20T15:00:00+08:00",
"client_charge_hours": "1.0000",
"is_third_party": false
}{
"data": {
"id": 1001,
"consumer_application_id": 21,
"managed_by_application_id": 21,
"updated_by_id": null,
"project_id": 3001,
"title": "新能源汽车产业交流会",
"type": "ONLINE",
"tags": [
"新能源"
],
"industry_id": null,
"industry_name": null,
"background": "交流行业趋势",
"description": "线上专题交流",
"outline": "市场趋势与技术路线",
"background_image_url": "https://example.com/meeting-cover.png",
"experts": [],
"starts_at": "2026-10-20T14:00:00+08:00",
"ends_at": "2026-10-20T15:00:00+08:00",
"client_charge_hours": "1.0000",
"customer_charge_hours": 1.0,
"is_third_party": false,
"registration_open": true,
"status": "published",
"created_at": "2026-10-15T10:00:00+08:00",
"updated_at": "2026-10-15T10:00:00+08:00"
},
"code": 200,
"message": "操作成功"
}GET /internal/v1/meetings/{meeting_id}/conference:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
{
"data": {
"id": 1001,
"consumer_application_id": 21,
"managed_by_application_id": 21,
"updated_by_id": null,
"project_id": 3001,
"title": "新能源汽车产业交流会",
"type": "ONLINE",
"tags": [
"新能源"
],
"industry_id": null,
"industry_name": null,
"background": "交流行业趋势",
"description": "线上专题交流",
"outline": "市场趋势与技术路线",
"background_image_url": "https://example.com/meeting-cover.png",
"experts": [],
"starts_at": "2026-10-20T14:00:00+08:00",
"ends_at": "2026-10-20T15:00:00+08:00",
"client_charge_hours": "1.0000",
"customer_charge_hours": 1.0,
"is_third_party": false,
"registration_open": true,
"status": "published",
"created_at": "2026-10-15T10:00:00+08:00",
"updated_at": "2026-10-15T10:00:00+08:00"
},
"code": 200,
"message": null
}GET /internal/v1/meetings/{meeting_id}/experts/meeting:finance。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
{
"data": [
{
"id": 9001,
"meeting_id": 1001,
"expert_id": 4001,
"task_id": 8002,
"payable_cost_id": null,
"settled_at": null,
"payment_hours": null,
"unit_price": null,
"currency": null,
"task_status": "ongoing",
"charge_status": "not_required",
"payment_status": "unpaid"
}
],
"code": 200,
"message": null
}POST /internal/v1/meetings/{meeting_id}/experts/meeting:write。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 是 | 应用内唯一的业务幂等键,1–128 字符,首尾无空格。 |
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
expert_id | body | integer | 是 | 目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。 最小:1 |
{
"expert_id": 4001
}{
"data": {
"id": 9001,
"meeting_id": 1001,
"expert_id": 4001,
"task_id": 8002,
"payable_cost_id": null,
"settled_at": null,
"payment_hours": null,
"unit_price": null,
"currency": null,
"task_status": "ongoing",
"charge_status": "not_required",
"payment_status": "unpaid"
},
"code": 200,
"message": "操作成功"
}POST /internal/v1/meetings/{meeting_id}/experts/{expert_id}/settlement/meeting:finance。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 是 | 应用内唯一的业务幂等键,1–128 字符,首尾无空格。 |
expert_id | path | string | 是 | 目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。 格式:"^\d+$" |
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
payment_hours | body | string (decimal) | 是 | 专家支付小时,非负十进制字符串,最多 6 位整数、4 位小数。 格式:"^-?\d{0,6}(?:\.\d{0,4})?$" |
{
"payment_hours": "1.2500"
}{
"data": {
"id": 9001,
"meeting_id": 1001,
"expert_id": 4001,
"task_id": 8002,
"payable_cost_id": 9201,
"settled_at": "2026-10-20T16:00:00+08:00",
"payment_hours": "1.2500",
"unit_price": "800.00",
"currency": "CNY",
"task_status": "ongoing",
"charge_status": "not_required",
"payment_status": "unpaid"
},
"code": 200,
"message": "操作成功"
}GET /internal/v1/meetings/{meeting_id}/join-link/meeting:join。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
client_contact_id | query | integer | 是 | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 |
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
{
"data": {
"join_url": "https://example.com/join/demo"
},
"code": 200,
"message": null
}GET /internal/v1/meetings/{meeting_id}/registration/registration:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
client_contact_id | query | integer | 是 | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 |
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
{
"data": {
"id": 1,
"meeting_id": 1,
"client_contact_id": 1,
"task_id": null,
"status": "confirmed",
"attendance": "pending",
"attend_requested": false,
"minutes_requested": false,
"task_status": null,
"charge_status": null,
"payment_status": null,
"created_at": "2026-10-15T10:00:00+08:00"
},
"code": 200,
"message": "操作成功"
}POST /internal/v1/meetings/{meeting_id}/registration/cancel/registration:cancel。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 是 | 应用内唯一的业务幂等键,1–128 字符,首尾无空格。 |
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
client_contact_id | body | integer | 是 | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 最小:1 |
{
"client_contact_id": 2001
}{
"data": {
"id": 7001,
"meeting_id": 1001,
"client_contact_id": 2001,
"task_id": 8001,
"status": "cancelled",
"attendance": "pending",
"attend_requested": true,
"minutes_requested": false,
"task_status": "ongoing",
"charge_status": "unbilled",
"payment_status": "not_required",
"created_at": "2026-10-15T10:00:00+08:00"
},
"code": 200,
"message": "操作成功"
}GET /internal/v1/meetings/{meeting_id}/registrations/registration:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
{
"data": [
{
"id": 7001,
"meeting_id": 1001,
"client_contact_id": 2001,
"task_id": 8001,
"status": "confirmed",
"attendance": "pending",
"attend_requested": true,
"minutes_requested": false,
"task_status": "ongoing",
"charge_status": "unbilled",
"payment_status": "not_required",
"created_at": "2026-10-15T10:00:00+08:00"
}
],
"code": 200,
"message": null
}POST /internal/v1/meetings/{meeting_id}/registrations/registration:create。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 是 | 应用内唯一的业务幂等键,1–128 字符,首尾无空格。 |
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
client_contact_id | body | integer | 是 | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 最小:1 |
project_id | body | integer | 否 | NDB 项目 ID。 最小:1 |
contract_id | body | integer | 否 | NDB 启用合同 ID。 最小:1 |
intent | body | IntentEnum | 否 | attend=参会,minutes=预约纪要;报名默认 attend,我的记录省略则不过滤意图。 枚举:["attend", "minutes"] 默认:"attend" |
{
"client_contact_id": 2001,
"intent": "attend",
"project_id": 3001,
"contract_id": 3101
}{
"data": {
"id": 7001,
"meeting_id": 1001,
"client_contact_id": 2001,
"task_id": 8001,
"status": "confirmed",
"attendance": "pending",
"attend_requested": true,
"minutes_requested": false,
"task_status": "ongoing",
"charge_status": "unbilled",
"payment_status": "not_required",
"created_at": "2026-10-15T10:00:00+08:00"
},
"code": 200,
"message": "操作成功"
}{
"client_contact_id": 2001,
"intent": "minutes"
}{
"code": 200,
"message": "操作成功",
"data": {
"id": 7001,
"meeting_id": 1001,
"client_contact_id": 2001,
"task_id": null,
"status": "reserved",
"attendance": "pending",
"attend_requested": false,
"minutes_requested": true,
"task_status": null,
"charge_status": null,
"payment_status": null,
"created_at": "2026-10-15T10:00:00+08:00"
}
}POST /internal/v1/meetings/{meeting_id}/registrations/{client_contact_id}/attendance/meeting:write。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 是 | 应用内唯一的业务幂等键,1–128 字符,首尾无空格。 |
client_contact_id | path | string | 是 | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 格式:"^\d+$" |
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
attendance | body | AttendanceEnum | 是 | pending=待确认,attended=已参会,no_show=未参会。 枚举:["pending", "attended", "no_show"] |
{
"attendance": "attended"
}{
"data": {
"id": 7001,
"meeting_id": 1001,
"client_contact_id": 2001,
"task_id": 8001,
"status": "attended",
"attendance": "attended",
"attend_requested": true,
"minutes_requested": false,
"task_status": "ongoing",
"charge_status": "unbilled",
"payment_status": "not_required",
"created_at": "2026-10-15T10:00:00+08:00"
},
"code": 200,
"message": "操作成功"
}POST /internal/v1/meetings/{meeting_id}/status/meeting:write。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Idempotency-Key | header | string | 是 | 应用内唯一的业务幂等键,1–128 字符,首尾无空格。 |
meeting_id | path | string | 是 | 会议 ID。 格式:"^\d+$" |
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
status | body | MeetingStatusStatusEnum | 是 | 资源状态,见枚举及本节业务说明。 枚举:["ended", "cancelled"] |
{
"status": "ended"
}{
"data": {
"id": 1001,
"consumer_application_id": 21,
"managed_by_application_id": 21,
"updated_by_id": null,
"project_id": 3001,
"title": "新能源汽车产业交流会",
"type": "ONLINE",
"tags": [
"新能源"
],
"industry_id": null,
"industry_name": null,
"background": "交流行业趋势",
"description": "线上专题交流",
"outline": "市场趋势与技术路线",
"background_image_url": "https://example.com/meeting-cover.png",
"experts": [],
"starts_at": "2026-10-20T14:00:00+08:00",
"ends_at": "2026-10-20T15:00:00+08:00",
"client_charge_hours": "1.0000",
"customer_charge_hours": 1.0,
"is_third_party": false,
"registration_open": false,
"status": "completed",
"created_at": "2026-10-15T10:00:00+08:00",
"updated_at": "2026-10-15T10:00:00+08:00"
},
"code": 200,
"message": "操作成功"
}GET /internal/v1/meetings/banners/conference:read。{
"data": [
{
"id": 1001,
"consumer_application_id": 21,
"managed_by_application_id": 21,
"updated_by_id": null,
"project_id": 3001,
"title": "新能源汽车产业交流会",
"type": "ONLINE",
"tags": [
"新能源"
],
"industry_id": null,
"industry_name": null,
"background": "交流行业趋势",
"description": "线上专题交流",
"outline": "市场趋势与技术路线",
"background_image_url": "https://example.com/meeting-cover.png",
"experts": [],
"starts_at": "2026-10-20T14:00:00+08:00",
"ends_at": "2026-10-20T15:00:00+08:00",
"client_charge_hours": "1.0000",
"customer_charge_hours": 1.0,
"is_third_party": false,
"registration_open": true,
"status": "published",
"created_at": "2026-10-15T10:00:00+08:00",
"updated_at": "2026-10-15T10:00:00+08:00"
}
],
"code": 200,
"message": null
}GET /internal/v1/meetings/mine/registration:read。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
client_contact_id | query | integer | 是 | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 |
intent | query | string | 否 | attend=参会,minutes=预约纪要;报名默认 attend,我的记录省略则不过滤意图。 枚举:["attend", "minutes"] |
page | query | integer | 否 | 页码,默认 1,最小 1。 |
page_size | query | integer | 否 | 每页数量 ,默认 20,范围 1–100。 |
{
"data": {
"items": [
{
"meeting": {
"id": 1001,
"consumer_application_id": 21,
"managed_by_application_id": 21,
"updated_by_id": null,
"project_id": 3001,
"title": "新能源汽车产业交流会",
"type": "ONLINE",
"tags": [
"新能源"
],
"industry_id": null,
"industry_name": null,
"background": "交流行业趋势",
"description": "线上专题交流",
"outline": "市场趋势与技术路线",
"background_image_url": "https://example.com/meeting-cover.png",
"experts": [],
"starts_at": "2026-10-20T14:00:00+08:00",
"ends_at": "2026-10-20T15:00:00+08:00",
"client_charge_hours": "1.0000",
"customer_charge_hours": 1.0,
"is_third_party": false,
"registration_open": true,
"status": "published",
"created_at": "2026-10-15T10:00:00+08:00",
"updated_at": "2026-10-15T10:00:00+08:00"
},
"registration": {
"id": 7001,
"meeting_id": 1001,
"client_contact_id": 2001,
"task_id": 8001,
"status": "confirmed",
"attendance": "pending",
"attend_requested": true,
"minutes_requested": false,
"task_status": "ongoing",
"charge_status": "unbilled",
"payment_status": "not_required",
"created_at": "2026-10-15T10:00:00+08:00"
}
}
],
"total": 1
},
"code": 200,
"message": null
}GET /internal/v1/users/user:read,管理员须单独授权。只读,无需 Idempotency-Key。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
id | query | integer | 否 | 员工ID精确匹配 |
email | query | string | 否 | 完整邮箱精确匹配,不区分大小写 |
wecom_user_id | query | string | 否 | 员工绑定的企业微信账号,精确且区分大小写,最多128字符;显式空值或首尾空白400 |
name | query | string | 否 | 中文名或英文名包含匹配 |
status | query | string | 否 | 默认active;inactive查询未激活/离职账号,不支持all |
page | query | integer | 否 | 默认1,最小1 |
page_size | query | integer | 否 | 默认20,范围1–100 |
{
"code": 200,
"message": null,
"data": {
"items": [
{
"id": 1001,
"email": "employee@example.com",
"name_cn": "示例员工",
"name_en": "Alex Example",
"title": "项目经理",
"status": "active",
"teams_id": 21,
"team_name": "示例项目组"
}
],
"total": 1,
"page": 1,
"page_size": 20
}
}GET /internal/v1/users/?wecom_user_id=zhangsan。仍默认只查active,可组合其他筛选;只是目录查询,不证明企微身份,响应不新增企微标识。此参数测试1.20.6b0起提供,生产1.20.6已提供。GET /internal/v1/experts/expert:read,管理员须单独授权。生产1.20.2 / 测试1.20.2b0已上线。沿用本项目AK/SK自动签名脚本,五个鉴权头均须正确签名;无需Idempotency-Key。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
keyword | query | string | 否 | 公开姓名、公司、职位、背景、分享话题包含匹配,最多256字符 |
page | query | integer | 否 | 默认1,最小1 |
page_size | query | integer | 否 | 默认20,范围1–100 |
{
"code": 200,
"message": null,
"data": {
"items": [
{
"id": 123,
"display_name": "公开昵称(虚构)",
"display_company": "示例公司",
"display_position": "行业顾问",
"display_background": "经人工确认的公开背景",
"avatar_url": "",
"industry": "科技",
"industry_id": null,
"tags": [
"技术"
],
"share_topics": "产业趋势",
"published_at": "2026-10-16T11:00:00",
"updated_at": "2026-10-16T11:00:00"
}
],
"total": 1,
"page": 1,
"page_size": 20
}
}GET /internal/v1/experts/{expert_id}/expert:read。expert_id为列表items[].id公开资料ID,不能传内部Candidates ID。{
"code": 200,
"message": null,
"data": {
"id": 123,
"display_name": "公开昵称(虚构)",
"display_company": "示例公司",
"display_position": "行业顾问",
"display_background": "经人工确认的公开背景",
"avatar_url": "",
"industry": "科技",
"industry_id": null,
"tags": [
"技术"
],
"share_topics": "产业趋势",
"published_at": "2026-10-16T11:00:00",
"updated_at": "2026-10-16T11:00:00"
}
}GET /internal/v1/clients/(无尾斜杠也支持,不重定向)。复用应用 AK/SK HMAC-SHA256,需管理员独立授予 client:read。client:resolve、user:read、conference:read 不授予此能力,不自动扩权。原 POST /internal/v1/clients/resolve/ 的身份解析、认证状态及权限契约保持不变。| Query 参数 | 类型 | 规则 |
|---|---|---|
| client_contact_id | integer | 联系人 ID,1–9223372036854775807 |
| phone | string | 精确匹配主手机号 phone 或备用手机号 phone1,1–64 字符,无首尾空白 |
+ 必须编码为 %2B,由公共签名客户端正确编码并签名。同一记录两个手机号同时命中只算一个联系人;多个不同联系人匹配则 409,调用方应改用联系人 ID。is_deleted=false 的记录;无公司或已删除公司联系人不返回。未标记为 false 的历史删除标志(null)也不纳入查询,与现有联系人过滤口径一致。{"code":200,"message":null,"data":{"client_contact_id":1001,"name":"李四","company_id":21,"company_name":"示例公司","position":"研究经理"}}data 始终仅有 client_contact_id、name、company_id、company_name、position 五项。name、company_name、position 允许 null,仍保留字段。不回传 phone/phone1、email、wechat、remark、认证状态或其他字段;数据库投影也仅加载五项所需列。| HTTP | code | 情况 |
|---|---|---|
| 400 | INVALID_REQUEST | 参数缺失、组合、重复、未知或格式错误 |
| 401 | authentication_failed | 缺少凭据、签名错误、过期、重放、应用停用等 |
| 403 | permission_denied | 未授予 client:read,或 IP 白名单不允许 |
| 404 | CONTACT_NOT_FOUND | 无有效匹配,包含联系人/公司删除或无公司 |
| 405 | method_not_allowed | POST、PUT、PATCH、DELETE 等不支持的方法 |
| 409 | AMBIGUOUS_CONTACT | 手机号命中多个不同有效联系人 |
{"code":"CONTACT_NOT_FOUND","message":"未找到有效客户联系人"}{"code":"AMBIGUOUS_CONTACT","message":"手机号匹配多个客户联系人,请改用 client_contact_id"}GET /internal/v1/experts/lookup/expert:lookup,管理员须单独显式授权。expert:read、user:read、client:read、client:resolve 均不授予此能力。使用应用 AK/SK 签名,沿用根目录自动签名前置脚本,不需要 Idempotency-Key。| 参数 | 位置 | 类型 | 约束 |
|---|---|---|---|
| phone | query | string,1–64 字符 | 与 email 严格二选一;精确匹配主/备用手机号,不规范化、不拼接区号 |
| query | email string,1–64 字符 | 与 phone 严格二选一;对主/备用邮箱做不区分大小写的精确匹配 |
+ 必须编码为 %2B。每次请求须生成新的 Nonce,签名包含实际 Query;Apifox 调试仅勾选一个查询参数。X-NDB-Access-Key、X-NDB-Timestamp、X-NDB-Nonce、X-NDB-Content-SHA256、X-NDB-Signature 由第2节签名协议或项目公共前置脚本生成;GET 空体摘要与签名仍必填,不发送 SK。{"code":200,"message":null,"data":{"expert_id":1001,"name":"张三","company":"示例公司","position":"研究经理"}}| 返回字段 | 类型 | 含义 |
|---|---|---|
| expert_id | integer | 内部 Candidates.id,不是 AI/目录公开资料的 PublicExpertProfile.id,也不是员工 ID 或客户联系人 ID |
| name | string 或 null | 专家真实姓名;已有空串保留 |
| company | string 或 null | 同一条最新工作履历的 org_cn;已有空串保留 |
| position | string 或 null | 同一条最新工作履历的 title;已有空串保留 |
Candidates.is_deleted=false,不按来源、锁定、可约、派生状态或 AI 公开池过滤,不包含 Galaxy 库。按不同 Candidates.id 计数,不按 original_id 合并;同一专家主/备用字段同时命中仍为一个,不同专家 ID 命中返回歧义错误,不提供候选列表。| HTTP | code | 说明 |
|---|---|---|
| 200 | 200 | 唯一命中,data 为四字段对象 |
| 400 | INVALID_REQUEST | 查询参数不合法 |
| 401 | authentication_failed | 鉴权失败、过期或重放 |
| 403 | permission_denied | 缺少独立 Scope 或来源 IP 不允许 |
| 404 | EXPERT_NOT_FOUND | 无匹配专家 |
| 405 | method_not_allowed | 非支持的请求方法 |
| 409 | AMBIGUOUS_EXPERT | 联系方式命中多个不同专家 ID |
{"code":"INVALID_REQUEST","message":"必须且只能提供一个查询条件"}
{"code":"authentication_failed","message":"应用鉴权失败"}
{"code":"permission_denied","message":"应用缺少 Scope:expert:lookup"}
{"code":"EXPERT_NOT_FOUND","message":"未找到匹配的专家"}
{"code":"method_not_allowed","message":"不支持此请求方法"}
{"code":"AMBIGUOUS_EXPERT","message":"联系方式匹配多个专家,无法唯一确定"}/users/、客户查询 /clients/、AI 公开专家 /experts/ 与本联系方式查询 /experts/lookup/ 的对象、ID 与 Scope 各自独立。| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 当前对象 ID;不同资源的 ID 不可混用。 |
consumer_application_id | integer | 消费应用 ID;指定其他应用时额外需要 meeting:publish。 |
managed_by_application_id | integer | 创建管理应用 ID。 |
updated_by_id | integer 或 null | 最近更新的员工 ID,可为空。 |
project_id | integer | NDB 项目 ID。 |
title | string | 标题。 |
type | MeetingTypeEnum | 资源类型,见枚举及本节业务说明。 枚举:["ONLINE", "SUMMARY", "REPORT"] |
tags | JSON | 标签数组。 |
industry_id | integer 或 null | NDB 行业 ID。 |
industry_name | string 或 null | 行业名称。 |
background | string | 背景介绍。 |
description | string | 详情说明。 |
outline | string | 提纲。 |
background_image_url | string (uri) | 背景图完整 HTTP(S) URL;不可携带账号密码。 |
experts | PublicExpert[] | 关联的可见公开专家数组;费用接口返回会议专家费用对象。 |
starts_at | string (date-time) | 会议开始时间,ISO 8601;建议显式使用 +08:00。 |
ends_at | string (date-time) | 会议结束时间,必须晚于 starts_at。 |
client_charge_hours | string (decimal) | 客户收费小时,非负十进制字符串,最多 6 位整数、4 位小数。 格式:"^-?\d{0,6}(?:\.\d{0,4})?$" |
customer_charge_hours | number (double) | 客户收费小时的数值展示字段。 |
is_third_party | boolean | 是否第三方会议,默认 false。 |
registration_open | boolean | 当前是否开放参会报名,最终以报名接口校验为准。 |
status | Status1aaEnum | 资源状态,见枚举及本节业务说明。 枚举:["published", "completed", "cancelled"] |
created_at | string (date-time) | 创建时间。 |
updated_at | string (date-time) | 更新时间。 |
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 当前对象 ID;不同资源的 ID 不可混用。 |
meeting_id | integer | 会议 ID。 |
client_contact_id | integer | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 |
task_id | integer 或 null | 关联业务 Task ID;纯纪要预约为 null。 |
status | StatusE04Enum | 资源状态,见枚举及本节业务说明。 枚举:["confirmed", "cancelled", "attended", "no_show", "reserved"] |
attendance | AttendanceEnum | pending=待确认,attended=已参会,no_show=未参会。 枚举:["pending", "attended", "no_show"] |
attend_requested | boolean | 是否曾请求参会;取消后仍可能为 true,应结合 status 判断。 |
minutes_requested | boolean | 是否曾预约纪要。 |
task_status | string 或 null | 关联 Task 状态。 |
charge_status | string 或 null | 客户收费状态。 |
payment_status | string 或 null | 专家支付状态;客户应收 Task 为 not_required。 |
created_at | string (date-time) | 创建时间。 |
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 当前对象 ID;不同资源的 ID 不可混用。 |
meeting_id | integer | 会议 ID。 |
expert_id | integer | 目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。 |
task_id | integer | 关联业务 Task ID;纯纪要预约为 null。 |
payable_cost_id | integer 或 null | 关联专家付款成本记录 ID。 |
settled_at | string (date-time) 或 null | 专家费用结算时间;未结算可为空,线上 Schema 未标明 nullable。 |
payment_hours | string (decimal) 或 null | 专家支付小时,非负十进制字符串,最多 6 位整数、4 位小数。 格式:"^-?\d{0,6}(?:\.\d{0,4})?$" |
unit_price | string (decimal) 或 null | 专家支付单价快照,十进制字符串。 格式:"^-?\d{0,8}(?:\.\d{0,2})?$" |
currency | string 或 null | 费率币种。 |
task_status | string | 关联 Task 状态。 |
charge_status | string | 客户收费状态。 |
payment_status | string | 专家支付状态;客户应收 Task 为 not_required。 |
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 当前对象 ID;不同资源的 ID 不可混用。 |
meeting_id | integer 或 null | 会议 ID。 |
meeting_title | string 或 null | |
type | ContentItemTypeEnum | 资源类型,见枚举及本节业务说明。 枚举:["minutes", "ai_minutes", "report"] |
title | string | 标题。 |
summary | string | 内容摘要。 |
body | string | 内容正文。 |
cover_url | string (uri) | 封面 URL。 |
industry | string | 行业名称。 |
industry_id | integer | NDB 行业 ID。 |
tags | JSON | 标签数组。 |
source | ContentItemSourceEnum | 内容来源 internal 或 third_party。 枚举:["internal", "third_party"] |
attachments | object[] | 公开附件数组;对象白名单字段 name、url、type、size。 |
published_at | string (date-time) | 发布时间。 |
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 当前对象 ID;不同资源的 ID 不可混用。 |
display_name | string | 公开展示姓名。 |
display_company | string | 公开展示公司。 |
display_position | string | 公开展示职位。 |
display_background | string | 公开展示背景。 |
avatar_url | string (uri) | 头像 URL,可为空字符串。 |
industry | string | 行业名称。 |
industry_id | integer | NDB 行业 ID。 |
tags | JSON | 标签数组。 |
share_topics | string | 可分享话题文本。 |
published_at | string (date-time) | 发布时间。 |
meetings | Meeting[] | 关联的可见会议数组。 |
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 当前对象 ID;不同资源的 ID 不可混用。 |
display_name | string | 公开展示姓名。 |
display_company | string | 公开展示公司。 |
display_position | string | 公开展示职位。 |
avatar_url | string | 头像 URL,可为空字符串。 |
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 当前对象 ID;不同资源的 ID 不可混用。 |
name | string | 名称。 |
public_profile | MeetingPublicProfile 或 null | 公开专家资料摘要;其中 id 是公开资料 ID。 |
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 当前对象 ID;不同资源的 ID 不可混用。 |
name | string | 名称。 |
background | string | 背景介绍。 |
outline | string | 提纲。 |
cover_url | string (uri) | 封面 URL。 |
industry | string | 行业名称。 |
industry_id | integer | NDB 行业 ID。 |
tags | JSON | 标签数组。 |
published_at | string (date-time) | 发布时间。 |
meetings | Meeting[] | 关联的可见会议数组。 |
contents | ContentItem[] | 关联的已发布内容数组。 |
experts | PublicExpertProfile[] | 关联的可见公开专家数组;费用接口返回会议专家费用对象。 |
| 字段 | 类型 | 说明 |
|---|---|---|
meeting | Meeting | 会议对象。 |
registration | Registration | 报名或预约对象。 |
| 字段 | 类型 | 说明 |
|---|---|---|
client_contact_id | integer | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 最小:1 |
requires_reauthentication | boolean | 匹配手机号是否需要重新认证。 |
reauthentication_since | string (date-time) 或 null | 要求重新认证的起始时间,可为空。 |
| 字段 | 类型 | 说明 |
|---|---|---|
join_url | string (uri) | 入会链接;会议公开 DTO 不包含,只由入会接口返回。 |
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 当前对象 ID;不同资源的 ID 不可混用。 |
expert_profile_id | integer | 公开专家资料 ID。 |
client_contact_id | integer | NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 |
message | string | 约访需求文字,最多 2000 字符;响应顶层 message 为提示文字。 |
status | ExpertInterviewRequestStatusEnum | 资源状态,见枚举及本节业务说明。 枚举:["pending", "contacted", "closed", "cancelled"] |
created_at | string (date-time) | 创建时间。 |
| HTTP | code | 含义与处理 |
|---|---|---|
| 401 | authentication_failed | 缺少请求头、AK/SK 无效、停用/过期、摘要/签名错误、时间戳过期、Nonce 重复或防重放服务不可用;校验时钟和签名,不盲目重放 |
| 403 | permission_denied | Scope 不足或来源 IP 不允许;联系管理员核对授权及服务端出口 IP |
| 400 | INVALID_REQUEST | 参数、时间、金额、关系或状态不合法;也可能缺少业务幂等键 |
| 400 | INVALID_CONSUMER_APPLICATION | 指定消费应用不存在、停用、过期或缺少 conference:read |
| 400 | CONTACT_NOT_BOUND | 联系人不存在或没有关联客户公司 |
| 404 | NOT_FOUND | 资源不存在、不可见或不在应用访问范围内 |
| 404 | CONTACT_NOT_FOUND | 已验证手机号没有匹配的有效客户联系人 |
| 409 | AMBIGUOUS_CONTACT | 手机号匹配多个联系人,由业务人员明确绑定 |
| 409 | NO_ACTIVE_CONTRACT | 无启用合同,由业务人员补充合同 |
| 409 | AMBIGUOUS_CONTRACT | 启用合同不唯一,需要明确 contract_id |
| 409 | AMBIGUOUS_PROJECT | 项目无法唯一确定,需要明确 project_id |
| 409 | IDEMPOTENCY_CONFLICT | 同业务键请求不一致,或试图改变已有报名的项目/合同 |
| 409 | MEETING_NOT_OPEN | 会议当前不可报名或尚未开始/已取消不能入会 |
| 409 | MINUTES_ALREADY_AVAILABLE | 人工纪要已开放,不能新增纪要预约;改为获取目录内容 |
| 409 | SETTLEMENT_LOCKED | 关联 Task 进入财务结算或不 可恢复,交业务人员处理 |
| 409 | JOIN_LINK_UNAVAILABLE | 会议尚未配置入会链接 |
| 403 | REGISTRATION_REQUIRED | 当前联系人没有有效参会报名或关联 Task 已失效 |
{"code":"authentication_failed","message":"应用签名校验失败。"}{"code":"NO_ACTIVE_CONTRACT","message":"该客户没有启用合同。"}| 问题 | 检查点 |
|---|---|
| ping 401 | AK 是否有效、五个请求头是否齐全、时钟是否秒级、请求体摘要与实际字节是否一致 |
| GET 签名错误 | 没有 query 时是否保留空行,空 body 是否误签成 {},尾 / 是否一致 |
| 中文或空格签名错误 | 先解码排序再 RFC 3986 编码;空格 %20;Python quote_via=quote;Node 需额外编码 !'()* |
| 第一次成功,重试 401 | Nonce 被复用;保留业务 Idempotency-Key,换时间戳和 Nonce |
| 写请求 409 | 检查是否复用其他操作的业务键、项目/合同是否一致及会议生命周期 |
| 列表为空或详情 404 | 当前应用归属、Scope、发布状态、发布时间、公开专家平台配置 |
| 无法入会 | 不是纯纪要预约、报名有效、Task 有效、已到开始时间、会议未取消且已配置链接 |
| 专家 ID 查不到 | 公开资料 ID 与内部专家 ID 是否混用 |
| 报名收费或专家支付与预期不同 | 由 NDB 合同/专家费率生成财务快 照;不能在请求体传任意金额覆盖 |
| 取消后仍有 Task | 取消报名不自动取消财务 Task,也不自动退款,需走业务财务流程 |
NDB第三方服务端接入文档.md:完整接入说明。openapi.yaml:24 个第三方 AK/SK 操作的精简契约,含 ping 响应补齐、会议列表外层类型与 settled_at 可空性修正。ndb_client.py、ndb-client.mjs:无第三方依赖的签名与调用实现。signature-vector.json:公开测试密钥的固定签名向量。examples.json:逐接口请求/响应示例,便于联调时检索。verification.md:离线检查结果与尚未运行的线上联调项。/schema/ 与 /v1/version/,核对日期 2026-10-15。签名及未完整体现在 Schema 中的约束,依据 NDB 后端 application_auth 与 meetings 模块补充。示例不是实际生产业务数据,未执行创建会议、报名、取消、结算、数据库或部署 操作。ndb_client.py;使用方式见第 3 节。ndb-client.mjs;使用方式见第 3 节。POST /internal/v1/users/authenticate/(尾斜杠可省略)。测试1.20.6b0已提供,生产1.20.6已提供。user:authenticate,已有 user:read 不包含验证权限。第三方后端通过 HTTPS 携带同一套五项 AK/SK 签名头调用;只序列化一次 JSON,对实际发送字节计算内容摘要和签名。无 Idempotency-Key。URL 不允许查询参数,密码不得放入 URL、日志或监控。| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
username | JSON body | string | 是 | 完整员工邮箱,最多64字符,匹配不区分大小写 |
password | JSON body | string | 是 | 员工输入的密码,最多1024字符,不裁剪首尾空白 |
{"username":"employee@example.com","password":"<员工输入的密码>"}id/email/name_cn/name_en/title/status/teams_id/team_name 八字段,无团队时团队字段为null。不返回 token、密码哈希、手机号、企微标识或权限。不生成或更新员工令牌、密码哈希、登录次数/时间/IP/更新时间,不影响原NDB会话;三方自行管理本系统会话。应用最近使用信息、签名Nonce、限流和不含凭据的验证审计仍会变化。{"code":200,"message":null,"data":{"id":1001,"email":"employee@example.com","name_cn":"示例员工","name_en":"Alex Example","title":"项目经理","status":"active","teams_id":null,"team_name":null}}| HTTP | code | 含义 |
|---|---|---|
| 400 | INVALID_REQUEST / parse_error | 字段、查询参数或JSON不合法 |
| 401 | authentication_failed | 应用签名失败、重复Nonce、应用停用或过期 |
| 401 | INVALID_CREDENTIALS | 员工不存在、停用、密码错误或邮箱大小写歧义,统一身份验证失败,不返回data |
| 403 | permission_denied | 缺独立Scope或出口IP不允许 |
| 405 | method_not_allowed | 只支持POST |
| 415 | unsupported_media_type | 仅支持application/json |
| 429 | throttled | 达到额度,按Retry-After秒数等待 |
| 503 | VERIFICATION_UNAVAILABLE | 共享限流缓存不可用,拒绝验证 |
Cache-Control: no-store。旧原始bcrypt最多72个UTF-8字节,超出拒绝;Django哈希与旧bcrypt均不在此接口升级。此能力由独立应用Scope控制,不改变网页密码登录开关;本次不提供第三方企业微信登录。