NDB 三方API
    • NDB 第三方服务端接入文档
    • Apifox 自动签名调试说明
    • internal
      • 验证应用鉴权
        GET
    • Catalog
      • 内容列表
        GET
      • 内容详情
        GET
      • 公开专家列表
        GET
      • 公开专家详情
        GET
      • 提交专家约访请求
        POST
      • 话题列表
        GET
      • 话题详情
        GET
    • Meetings
      • 解析客户联系人
        POST
      • 会议列表
        GET
      • 创建会议
        POST
      • 会议详情
        GET
      • 查询会议专家费用
        GET
      • 添加会议专家
        POST
      • 结算会议专家费用
        POST
      • 获取入会链接
        GET
      • 查询单人报名或预约
        GET
      • 取消参会报名
        POST
      • 会议报名与预约列表
        GET
      • 参会报名或预约纪要
        POST
      • 登记参会情况
        POST
      • 结束或取消会议
        POST
      • 会议轮播图
        GET
      • 我的报名与预约
        GET
    • Users
      • 查询 NDB 员工基本资料
      • 验证员工邮箱密码并返回基本资料(不签发令牌)
    • Experts
      • 按手机号或邮箱精确查询专家基本资料
      • 查询 AI 平台专家公开资料
      • 读取 AI 平台专家公开详情
    • Clients
      • 精确查询客户联系人资料

    NDB 第三方服务端接入文档

    版本:2026-10-22 · 生产 NDB 后端 1.20.6 / 测试 1.20.6b0。本轮员工密码验证与企业微信账号筛选已在两环境提供。
    本文面向第三方服务端开发者,覆盖应用 AK/SK 鉴权、签名、Python 与 Node.js 调用,以及会议、客户联系人查询与解析、员工查询、专家联系方式查询、报名、内容、话题、公开专家和管理接口。接入者使用独立应用身份,并仅在获授的 Scope 与数据归属范围内访问。
    本文按生产 OpenAPI 整理,并依据后端签名与业务实现补齐约束。所有请求和响应示例均为虚构数据,不含真实客户、专家或凭证。接口字段及示例已做离线检查;尚未以实际第三方凭证完成线上业务联调。

    1 接入准备#

    生产域名:https://crm-api.mindsetech.com
    业务前缀:/internal/v1,下文完整路径均已包含此前缀。
    编码:UTF-8;有请求体时使用 Content-Type: application/json; charset=utf-8。
    在线 Swagger · 完整线上 OpenAPI;随附 openapi.yaml 只包含第三方应用接口,可导入 Apifox/Postman。该文件对线上缺少响应定义的 ping 做了补齐,同时依据返回实现修正会议列表误包裹的数组层,以及 Expert.settled_at 的 nullable;其余结构保留线上契约。
    由 NDB 管理员在「设置 → 应用管理」为每个接入方创建独立应用,交付 Access Key(AK)和 Secret Key(SK),配置 Scope、有效期及出口 IP 白名单。SK 只在创建和轮换时返回一次,轮换后旧 SK 立即失效,AK 不变。
    AK/SK 仅保存在接入方服务端的机密管理系统中。浏览器、移动 App、小程序应调用自己的服务端,由服务端代签。凭证不要放入 URL、代码库或日志。应用鉴权不等于终端客户身份认证;手机号及联系人绑定由接入方服务端验证。
    建议联调顺序:创建应用与授权 → ping → 会议或目录列表 → 已验证手机号解析 → 报名/预约 → 查询记录 → 在允许时间获取入会链接。写操作先使用双方约定的测试应用、会议及联系人。

    Scope 与数据范围#

    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按手机号或邮箱精确查询内部专家的姓名、公司、职位;独立全局只读权限,需管理员单独显式授权
    普通渠道应用按业务需要分别授予应用连通、会议/目录读取、报名创建/读取/取消和入会能力;全局客户解析 client:resolve、客户查询 client:read、员工查询 user:read、AI 公开资料 expert:read、专家联系方式查询 expert:lookup 均需管理员单独显式授权。会议维护、跨应用发布及财务 Scope 也须按需单独授予。X-NDB-Scope 不能扩权,权限以服务端应用配置为准。Scope 注册表中的 registration:check 当前没有独立线上路由,报名资格由报名接口校验。
    会议允许其消费应用或创建管理应用访问,两者仍需各自 Scope;其他应用访问返回不存在。/catalog/ 下的内容、话题与公开专家目录按消费应用隔离,需已发布且发布时间已到。公开专家还要求内部专家未删除并开启 WECHAT_MINI_APP 公开平台;当前目录仍采用此平台条件,接入其他渠道前应确认发布配置。目录不返回内部专家联系方式、支付资料或全量专家库。
    AI专家接口 /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。

    2 AK/SK 签名协议#

    每次请求携带以下五个请求头:
    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,小写十六进制

    2.1 签名原文#

    按以下顺序拼接六行,行间仅一个 LF (\n),第六行后不加换行:
    HTTP_METHOD
    REQUEST_PATH
    CANONICAL_QUERY_STRING
    TIMESTAMP
    NONCE
    CONTENT_SHA256
    1.
    HTTP_METHOD 使用大写,例如 GET、POST。
    2.
    REQUEST_PATH 使用实际发送的完整路径,例如 /internal/v1/meetings/,不含域名和 ?query。是否有尾部 / 会影响签名,不能签名后改路径。建议固定使用文档中的尾斜杠形式,拒绝自动跳转。
    3.
    查询串先解析为解码后的 key/value 对,保留重复参数和空值,然后按 key、value 的解码字符串顺序排序;分别按 RFC 3986 编码后用 = 和 & 拼接。空格编码 %20,不是 +;~ 保留;其他如 !、'、(、)、* 编码。原始查询中的 + 会解码为空格,字面加号应发送 %2B。不要重复编码。
    4.
    没有查询参数时,第三行为空行,不能删掉。
    5.
    CONTENT_SHA256 = SHA256(body_bytes).hexdigest()。无请求体时使用空字节串;其摘要固定为 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855。空请求体与 {} 的摘要不同。
    6.
    SIGNATURE = HMAC_SHA256(UTF8(SK), UTF8(canonical_request)).hexdigest();SK 按原字符串 UTF-8 使用,不做 Base64 解码。
    JSON 键顺序、空格、转义和末尾换行会改变原始字节摘要。先序列化一次,再用同一份字节签名和发送;不要在签名后重新序列化。服务端业务幂等的 JSON 归一化与 HMAC 原始字节签名是两回事。
    时间戳允许偏差默认 300 秒,Nonce 防重放缓存默认 600 秒,生产可配置。客户端保持系统时钟同步;同一 Nonce 在缓存有效期内不能复用。SK 和 Authorization 不参与签名原文;本协议也不需要额外 Bearer Token。

    2.2 查询参数归一化示例#

    原始查询: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%90

    2.3 固定签名测试向量#

    随附 signature-vector.json 使用公开虚构测试密钥,包含固定时间戳、Nonce、请求体、规范原文和预期签名,可用来核对不同语言实现。固定向量只供离线测试,不可直接用于线上请求。
    测试 SK: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
    7c74527f902ac8846267cdf11fc5cd3c1e9acb78d1a5bfba91592c5738dcee93
    预期 X-NDB-Signature:
    c5722996f60fecc17d67dd88e4c9a98279bf904675847fadd207d008bd4cb30a

    3 调用示例#

    随附 ndb_client.py(Python 3.9+ 标准库)和 ndb-client.mjs(Node.js 20+)可直接使用。两者从环境变量读取 AK/SK,禁止重定向,不自动重试。请由机密管理系统注入 NDB_ACCESS_KEY、NDB_SECRET_KEY,可选 NDB_BASE_URL 默认为生产 HTTPS 域名。不要在聊天或日志中打印密钥。

    3.1 Python#

    将文件置于同一目录,直接执行 python3 ndb_client.py 只调用 ping。业务调用:

    3.2 Node.js#

    直接执行 node ndb-client.mjs 只调用 ping。业务调用:

    3.3 curl 请求形状#

    以下变量需由你自己的签名器生成,示例仅展示请求格式:
    POST 如用 --data-binary @body.json,必须签名该文件的完整字节,包括可能存在的末尾换行,并添加 Content-Type 及需要的 Idempotency-Key。不要使用 curl -L。

    4 公共请求和响应约定#

    分页、日期和数值#

    分页列表默认 page=1&page_size=20,page>=1,page_size=1–100,返回 data.items 和 data.total;报名全量列表、会议专家费用列表与轮播图返回数组,不使用分页。
    会议开始、结束时间按上海业务时间解释,建议发送带 +08:00 的 ISO 8601 时间。其他时间字段也按 ISO 8601 读取并保留时区。小时、金额等 decimal 字段按字符串处理,避免二进制浮点误差。所有示例 ID 都是虚构值,不能直接当作生产 ID。

    响应信封#

    成功 HTTP 200,code 为数值 200,message 可为 null、操作成功或鉴权成功,具体业务值位于 data。会议与目录业务失败使用真实 HTTP 4xx 和字符串业务 code;ping 使用公共异常处理,鉴权失败 code 可为 authentication_failed,权限失败可为数值 403。客户端必须同时检查 HTTP 状态和 code,不要依赖 message 文案。

    幂等与重试#

    除手机号解析以外,本文件所有 POST 写接口均要求 Idempotency-Key。业务键按应用唯一,1–128 字符且首尾无空格;同一操作重试保留业务键、method、path 和 JSON 内容,时间戳与 HMAC Nonce 重新生成。不同业务操作不可共用一个键。
    成功响应快照与业务写入一起提交;相同键和请求返回原成功快照,内容或路径改变返回 IDEMPOTENCY_CONFLICT。原快照可能早于后续状态变化,要获取当前状态请再 GET。失败操作不占用成功业务键。网络超时或连接断开时,保留原业务键重新签名重试;不要凭超时判定业务未执行。对 4xx 先修复参数、权限或业务前置条件,避免无差别循环重试。

    ID 对应关系#

    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)。
    Meeting DTO 的 experts[].id 是内部专家 ID,而 experts[].public_profile.id 是公开资料 ID;不要互换。目录详情不提供全量内部专家档案。
    /internal/v1/experts/{expert_id}/ 使用公开资料 ID(列表 data.items[].id),不是内部 Candidates ID。

    5 接口索引#

    编号接口用途Scope
    01GET /internal/v1/application-auth/ping/验证应用鉴权application:ping
    02GET /internal/v1/catalog/content/内容列表conference:read
    03GET /internal/v1/catalog/content/{content_id}/内容详情conference:read
    04GET /internal/v1/catalog/experts/公开专家列表conference:read
    05GET /internal/v1/catalog/experts/{expert_id}/公开专家详情conference:read
    06POST /internal/v1/catalog/experts/{expert_id}/interview-requests/提交专家约访请求registration:create
    07GET /internal/v1/catalog/topics/话题列表conference:read
    08GET /internal/v1/catalog/topics/{topic_id}/话题详情conference:read
    09POST /internal/v1/clients/resolve/解析客户联系人client:resolve
    10GET /internal/v1/meetings/会议列表conference:read
    11POST /internal/v1/meetings/创建会议meeting:write
    12GET /internal/v1/meetings/{meeting_id}/会议详情conference:read
    13GET /internal/v1/meetings/{meeting_id}/experts/查询会议专家费用meeting:finance
    14POST /internal/v1/meetings/{meeting_id}/experts/添加会议专家meeting:write
    15POST /internal/v1/meetings/{meeting_id}/experts/{expert_id}/settlement/结算会议专家费用meeting:finance
    16GET /internal/v1/meetings/{meeting_id}/join-link/获取入会链接meeting:join
    17GET /internal/v1/meetings/{meeting_id}/registration/查询单人报名或预约registration:read
    18POST /internal/v1/meetings/{meeting_id}/registration/cancel/取消参会报名registration:cancel
    19GET /internal/v1/meetings/{meeting_id}/registrations/会议报名与预约列表registration:read
    20POST /internal/v1/meetings/{meeting_id}/registrations/参会报名或预约纪要registration:create
    21POST /internal/v1/meetings/{meeting_id}/registrations/{client_contact_id}/attendance/登记参会情况meeting:write
    22POST /internal/v1/meetings/{meeting_id}/status/结束或取消会议meeting:write
    23GET /internal/v1/meetings/banners/会议轮播图conference:read
    24GET /internal/v1/meetings/mine/我的报名与预约registration:read
    25GET /internal/v1/users/查询 NDB 员工基本资料user:read
    26GET /internal/v1/experts/查询 AI 平台专家公开资料expert:read
    27GET /internal/v1/experts/{expert_id}/读取 AI 平台专家公开详情expert:read
    28GET /internal/v1/clients/精确查询客户联系人资料(目前仅生产提供)client:read
    29GET /internal/v1/experts/lookup/按手机号或邮箱精确查询专家基本资料(生产与测试均提供)expert:lookup
    30POST /internal/v1/users/authenticate/验证员工邮箱密码并返回基本资料(测试1.20.6b0起)user:authenticate

    6 各接口参数和返回示例#

    以下省略所有接口共用的五个鉴权请求头。示例是完整 JSON 响应信封;查询和 body 参数不要混放。

    6.1 验证应用鉴权#

    GET /internal/v1/application-auth/ping/
    Scope:application:ping。
    路径、查询及额外业务请求头:无。
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "code": 200,
      "message": "鉴权成功",
      "data": {
        "application_id": 21,
        "application_name": "第三方渠道测试应用",
        "access_key": "ndb_example_access_key"
      }
    }
    业务说明:该接口只验证应用鉴权,成功会返回应用 ID、名称和 AK,不返回 SK。线上原始 Schema 未定义响应体,此处按后端实现补齐。

    6.2 内容列表#

    GET /internal/v1/catalog/content/
    Scope:conference:read。
    参数位置类型必填说明
    keywordquerystring否关键词;按对应资源的标题、简介等文本搜索。
    pagequeryinteger否页码,默认 1,最小 1。
    page_sizequeryinteger否每页数量,默认 20,范围 1–100。
    typequerystring否资源类型,见枚举及本节业务说明。
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:type 支持 minutes(人工纪要)、ai_minutes(AI 纪要)、report(报告)和 summary(minutes 与 ai_minutes 合集);省略不过滤类型。正文和附件只返回公开内容。

    6.3 内容详情#

    GET /internal/v1/catalog/content/{content_id}/
    Scope:conference:read。
    参数位置类型必填说明
    content_idpathstring是内容 ID。 格式:"^\d+$"
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:不存在、未发布、发布时间未到或归属其他应用返回 404。attachments 仅返回 name、url、type、size 白名单字段;某条附件可以缺少其中部分字段。

    6.4 公开专家列表#

    GET /internal/v1/catalog/experts/
    Scope:conference:read。
    参数位置类型必填说明
    keywordquerystring否关键词;按对应资源的标题、简介等文本搜索。
    pagequeryinteger否页码,默认 1,最小 1。
    page_sizequeryinteger否每页数量,默认 20,范围 1–100。
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:id 是公开资料 ID;关键词检索公开姓名、公司、职位、背景及可分享话题。只返回已发布且通过公开平台条件的资料。

    6.5 公开专家详情#

    GET /internal/v1/catalog/experts/{expert_id}/
    Scope:conference:read。
    参数位置类型必填说明
    expert_idpathstring是目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。 格式:"^\d+$"
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:路径 expert_id 为公开资料 ID。关闭公开平台或未发布的专家不可见,不回退内部姓名、联系方式或履历。

    6.6 提交专家约访请求#

    POST /internal/v1/catalog/experts/{expert_id}/interview-requests/
    Scope:registration:create。
    参数位置类型必填说明
    Idempotency-Keyheaderstring是应用内唯一的业务幂等键,1–128 字符,首尾无空格。
    expert_idpathstring是目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。 格式:"^\d+$"
    请求体(JSON):
    参数位置类型必填说明
    client_contact_idbodyinteger是NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 最小:1
    messagebodystring否约访需求文字,最多 2000 字符;响应顶层 message 为提示文字。 最长字符数:2000
    请求体示例:
    {
      "client_contact_id": 2001,
      "message": "希望交流新能源供应链趋势"
    }
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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": "操作成功"
    }
    业务说明:路径 expert_id 为公开资料 ID。只创建约访请求;不会创建财务 Task、支付或发送通知。请求联系人必须存在且未删除,客户端身份归属由接入方服务端验证。

    6.7 话题列表#

    GET /internal/v1/catalog/topics/
    Scope:conference:read。
    参数位置类型必填说明
    keywordquerystring否关键词;按对应资源的标题、简介等文本搜索。
    pagequeryinteger否页码,默认 1,最小 1。
    page_sizequeryinteger否每页数量,默认 20,范围 1–100。
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:按名称、背景、提纲和行业关键词检索已发布话题。

    6.8 话题详情#

    GET /internal/v1/catalog/topics/{topic_id}/
    Scope:conference:read。
    参数位置类型必填说明
    topic_idpathstring是话题 ID。 格式:"^\d+$"
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:返回话题及其可见关联会议、已发布内容和公开专家,关联数组可为空。

    6.9 解析客户联系人#

    POST /internal/v1/clients/resolve/
    Scope:client:resolve。
    路径、查询及额外业务请求头:无。
    请求体(JSON):
    参数位置类型必填说明
    verified_phonebodystring是服务端已验证的手机号,可选前导 +,其后 6–20 位数字;不是手机号验证码。 格式:"^\+?[0-9]{6,20}$"
    channelbodyChannelEnum是当前仅支持 wechat。 枚举:["wechat"]
    请求体示例:
    {
      "verified_phone": "13800000000",
      "channel": "wechat"
    }
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "data": {
        "client_contact_id": 2001,
        "requires_reauthentication": false,
        "reauthentication_since": null
      },
      "code": 200,
      "message": null
    }
    业务说明:verified_phone 必须来自接入方已经验证的身份,当前 channel 仅支持 wechat,其他渠道不可自行伪装来源。无匹配返回 CONTACT_NOT_FOUND,多匹配返回 AMBIGUOUS_CONTACT;requires_reauthentication=true 时应重新验证手机号后再沿用联系人绑定。此 POST 不要求业务幂等键,仍需新 Nonce。

    6.10 会议列表#

    GET /internal/v1/meetings/
    Scope:conference:read。
    参数位置类型必填说明
    datequerystring否会议开始日期,YYYY-MM-DD;与 month 同传时叠加过滤。
    keywordquerystring否关键词;按对应资源的标题、简介等文本搜索。
    monthquerystring否会议开始月份,YYYY-MM。
    pagequeryinteger否页码,默认 1,最小 1。
    page_sizequeryinteger否每页数量,默认 20,范围 1–100。
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:支持 keyword、date、month 组合筛选。date 与 month 都按 starts_at 过滤;返回包括该应用有权访问的已结束或取消会议。

    6.11 创建会议#

    POST /internal/v1/meetings/
    Scope:meeting:write。
    参数位置类型必填说明
    Idempotency-Keyheaderstring是应用内唯一的业务幂等键,1–128 字符,首尾无空格。
    请求体(JSON):
    参数位置类型必填说明
    consumer_application_idbodyinteger否消费应用 ID;指定其他应用时额外需要 meeting:publish。 最小:1
    project_idbodyinteger是NDB 项目 ID。 最小:1
    titlebodystring是标题。 最长字符数:256
    typebodyMeetingTypeEnum否资源类型,见枚举及本节业务说明。 枚举:["ONLINE", "SUMMARY", "REPORT"] 默认:"ONLINE"
    tagsbodystring[]否标签数组。
    industry_idbodyinteger 或 null否NDB 行业 ID。
    backgroundbodystring否背景介绍。 默认:""
    descriptionbodystring否详情说明。
    outlinebodystring否提纲。
    background_image_urlbodystring (uri)否背景图完整 HTTP(S) URL;不可携带账号密码。 最长字符数:2048
    join_urlbodystring (uri)否入会链接;会议公开 DTO 不包含,只由入会接口返回。 最长字符数:2048
    starts_atbodystring (date-time)是会议开始时间,ISO 8601;建议显式使用 +08:00。
    ends_atbodystring (date-time)是会议结束时间,必须晚于 starts_at。
    client_charge_hoursbodystring (decimal)是客户收费小时,非负十进制字符串,最多 6 位整数、4 位小数。 格式:"^-?\d{0,6}(?:\.\d{0,4})?$"
    is_third_partybodyboolean否是否第三方会议,默认 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
    }
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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": "操作成功"
    }
    业务说明:project_id 必须是已存在的有效项目,接口不会自动创建项目。省略 consumer_application_id 表示当前应用自有会议;指定其他应用需额外 meeting:publish,目标应用需启用、未过期且有 conference:read。新会议直接为 published,结束时间须晚于开始时间。创建后不能通过状态更新转移应用归属;join_url 不出现在公开 Meeting DTO。

    6.12 会议详情#

    GET /internal/v1/meetings/{meeting_id}/
    Scope:conference:read。
    参数位置类型必填说明
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:返回当前应用作为消费方或创建管理方有权读取的会议。公开 DTO 不包含入会链接;experts 按公开资料可见条件过滤。

    6.13 查询会议专家费用#

    GET /internal/v1/meetings/{meeting_id}/experts/
    Scope:meeting:finance。
    参数位置类型必填说明
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:返回会议专家关联及财务快照数组;需要 meeting:finance,公开目录 Scope 不足。未结算 settled_at 实际可为 null,线上 Schema 对此缺少 nullable 声明,交付 OpenAPI 已补齐,接入方应兼容。

    6.14 添加会议专家#

    POST /internal/v1/meetings/{meeting_id}/experts/
    Scope:meeting:write。
    参数位置类型必填说明
    Idempotency-Keyheaderstring是应用内唯一的业务幂等键,1–128 字符,首尾无空格。
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体(JSON):
    参数位置类型必填说明
    expert_idbodyinteger是目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。 最小:1
    请求体示例:
    {
      "expert_id": 4001
    }
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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": "操作成功"
    }
    业务说明:body expert_id 必须是内部 Candidates ID。会议已结束或取消不能新增;关联时建立专家应付 Task,不提前读取支付费率。响应 id 是 MeetingExpert 关联 ID,不是 expert_id。

    6.15 结算会议专家费用#

    POST /internal/v1/meetings/{meeting_id}/experts/{expert_id}/settlement/
    Scope:meeting:finance。
    参数位置类型必填说明
    Idempotency-Keyheaderstring是应用内唯一的业务幂等键,1–128 字符,首尾无空格。
    expert_idpathstring是目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。 格式:"^\d+$"
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体(JSON):
    参数位置类型必填说明
    payment_hoursbodystring (decimal)是专家支付小时,非负十进制字符串,最多 6 位整数、4 位小数。 格式:"^-?\d{0,6}(?:\.\d{0,4})?$"
    请求体示例:
    {
      "payment_hours": "1.2500"
    }
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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": "操作成功"
    }
    业务说明:路径 expert_id 为内部 Candidates ID。会后才可填写非负 payment_hours,服务端读取当前专家费率/币种并建立或更新原付款成本,返回财务快照。相同小时重试保留原费率;修改小时受结算锁定条件限制。登记结算不会自动向专家打款。示例时间表示会后状态。

    6.16 获取入会链接#

    GET /internal/v1/meetings/{meeting_id}/join-link/
    Scope:meeting:join。
    参数位置类型必填说明
    client_contact_idqueryinteger是NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "data": {
        "join_url": "https://example.com/join/demo"
      },
      "code": 200,
      "message": null
    }
    业务说明:需 meeting:join、有效参会报名、关联 Task 未取消/失败/删除,且到达 starts_at 并且会议未取消;纯纪要预约无权获取。已结束但未取消的会议仍可查询原有效报名链接,链接未配置返回 JOIN_LINK_UNAVAILABLE。

    6.17 查询单人报名或预约#

    GET /internal/v1/meetings/{meeting_id}/registration/
    Scope:registration:read。
    参数位置类型必填说明
    client_contact_idqueryinteger是NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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": "操作成功"
    }
    业务说明:未产生报名或预约时 data 显式为 null,例如 {"code":200,"message":"操作成功","data":null}。有记录时返回同一个统一 Registration。

    6.18 取消参会报名#

    POST /internal/v1/meetings/{meeting_id}/registration/cancel/
    Scope:registration:cancel。
    参数位置类型必填说明
    Idempotency-Keyheaderstring是应用内唯一的业务幂等键,1–128 字符,首尾无空格。
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体(JSON):
    参数位置类型必填说明
    client_contact_idbodyinteger是NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 最小:1
    请求体示例:
    {
      "client_contact_id": 2001
    }
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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": "操作成功"
    }
    业务说明:取消原参会报名并保留原记录、意图和 Task;不会自动取消 Task、退款或删除纪要预约。纯纪要预约不能借此接口取消参会。进入财务结算后拒绝直接取消。

    6.19 会议报名与预约列表#

    GET /internal/v1/meetings/{meeting_id}/registrations/
    Scope:registration:read。
    参数位置类型必填说明
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:返回会议全部报名和预约记录数组,无分页;只需要 registration:read。接入方需自行限制哪些终端用户可查看此管理能力。

    6.20 参会报名或预约纪要#

    POST /internal/v1/meetings/{meeting_id}/registrations/
    Scope:registration:create。
    参数位置类型必填说明
    Idempotency-Keyheaderstring是应用内唯一的业务幂等键,1–128 字符,首尾无空格。
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体(JSON):
    参数位置类型必填说明
    client_contact_idbodyinteger是NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 最小:1
    project_idbodyinteger否NDB 项目 ID。 最小:1
    contract_idbodyinteger否NDB 启用合同 ID。 最小:1
    intentbodyIntentEnum否attend=参会,minutes=预约纪要;报名默认 attend,我的记录省略则不过滤意图。 枚举:["attend", "minutes"] 默认:"attend"
    请求体示例:
    {
      "client_contact_id": 2001,
      "intent": "attend",
      "project_id": 3001,
      "contract_id": 3101
    }
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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": "操作成功"
    }
    业务说明:intent 默认 attend。参会需会议开放并校验客户、项目和启用合同;可选 project_id/contract_id 省略时尝试唯一解析,歧义需业务人员明确,不可随机选值。intent=minutes 为纯纪要预约,task_id/task_status/charge_status/payment_status 均为 null,status=reserved;同会议同联系人复用统一记录,先预约后参会仅补建一个客户应收 Task。非取消线上会议在开始或结束后仍可预约纪要,但人工纪要已公开时新增预约返回 MINUTES_ALREADY_AVAILABLE。已预约的相同意图成功请求可复用原事实。
    纯纪要预约请求与返回示例:
    {
      "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"
      }
    }

    6.21 登记参会情况#

    POST /internal/v1/meetings/{meeting_id}/registrations/{client_contact_id}/attendance/
    Scope:meeting:write。
    参数位置类型必填说明
    Idempotency-Keyheaderstring是应用内唯一的业务幂等键,1–128 字符,首尾无空格。
    client_contact_idpathstring是NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 格式:"^\d+$"
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体(JSON):
    参数位置类型必填说明
    attendancebodyAttendanceEnum是pending=待确认,attended=已参会,no_show=未参会。 枚举:["pending", "attended", "no_show"]
    请求体示例:
    {
      "attendance": "attended"
    }
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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": "操作成功"
    }
    业务说明:路径 client_contact_id 是客户联系人 ID,不是报名记录 ID。确认 attended/no_show 需会议已结束且 ends_at 已到;仅时间已过但会议仍未结束不允许确认。pending 保留待确认语义。

    6.22 结束或取消会议#

    POST /internal/v1/meetings/{meeting_id}/status/
    Scope:meeting:write。
    参数位置类型必填说明
    Idempotency-Keyheaderstring是应用内唯一的业务幂等键,1–128 字符,首尾无空格。
    meeting_idpathstring是会议 ID。 格式:"^\d+$"
    请求体(JSON):
    参数位置类型必填说明
    statusbodyMeetingStatusStatusEnum是资源状态,见枚举及本节业务说明。 枚举:["ended", "cancelled"]
    请求体示例:
    {
      "status": "ended"
    }
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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": "操作成功"
    }
    业务说明:status 输入 ended 或 cancelled;ended 成功响应映射为 completed。未到 ends_at 不能结束;已结束或已取消会议不能重新开启。状态变更不会自动完成、取消或支付关联 Task。示例表示会后结束操作。

    6.23 会议轮播图#

    GET /internal/v1/meetings/banners/
    Scope:conference:read。
    路径、查询及额外业务请求头:无。
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:返回 Meeting 数组,不是分页对象;从本应用可见会议中按轮播配置筛选。

    6.24 我的报名与预约#

    GET /internal/v1/meetings/mine/
    Scope:registration:read。
    参数位置类型必填说明
    client_contact_idqueryinteger是NDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。
    intentquerystring否attend=参会,minutes=预约纪要;报名默认 attend,我的记录省略则不过滤意图。 枚举:["attend", "minutes"]
    pagequeryinteger否页码,默认 1,最小 1。
    page_sizequeryinteger否每页数量,默认 20,范围 1–100。
    请求体:无。
    调用路径示例:
    成功返回示例(HTTP 200):
    {
      "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
    }
    业务说明:client_contact_id 必填;intent=attend/minutes 过滤历史请求意图,省略返回全部业务记录。已取消参会仍可能 attend_requested=true,需结合 registration.status 判断当前有效性。

    6.25 查询 NDB 员工基本资料#

    GET /internal/v1/users/
    Scope:user:read,管理员须单独授权。只读,无需 Idempotency-Key。
    参数位置类型必填说明
    idqueryinteger否员工ID精确匹配
    emailquerystring否完整邮箱精确匹配,不区分大小写
    wecom_user_idquerystring否员工绑定的企业微信账号,精确且区分大小写,最多128字符;显式空值或首尾空白400
    namequerystring否中文名或英文名包含匹配
    statusquerystring否默认active;inactive查询未激活/离职账号,不支持all
    pagequeryinteger否默认1,最小1
    page_sizequeryinteger否默认20,范围1–100
    过滤条件按AND组合,按员工ID升序。只返回基本账号与团队信息,不返回密码、令牌、电话、微信标识或RBAC权限。
    {
      "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已提供。

    6.26 查询 AI 平台专家公开资料#

    GET /internal/v1/experts/
    Scope:expert:read,管理员须单独授权。生产1.20.2 / 测试1.20.2b0已上线。沿用本项目AK/SK自动签名脚本,五个鉴权头均须正确签名;无需Idempotency-Key。
    参数位置类型必填说明
    keywordquerystring否公开姓名、公司、职位、背景、分享话题包含匹配,最多256字符
    pagequeryinteger否默认1,最小1
    page_sizequeryinteger否默认20,范围1–100
    按公开资料ID升序,未知参数拒绝。仅返回勾选AI_PLATFORM、专家未删除、公开资料published且发布时间非空并已到时的数据。
    {
      "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
      }
    }
    AI平台与微信小程序独立勾选,共用人工确认的公开资料,不读取或自动同步内部档案。来源由服务端MEETING_WEB_APPLICATION_NAME绑定的现有公开资料应用决定;消费者自身应用下的其他资料不会混入,也不接受application_id参数。来源应用须启用、未过期并有conference:read;配置异常返回503,不能绕过。
    Apifox接口文档。常见错误:400 INVALID_REQUEST(非法分页或未知参数)、401鉴权失败、403缺少expert:read或IP不允许、405不支持写入方法、503来源不可用。

    6.27 读取 AI 平台专家公开详情#

    GET /internal/v1/experts/{expert_id}/
    Scope: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"
      }
    }
    隐藏、已删除、不存在或其他来源的公开资料均返回404 / NOT_FOUND,不回退内部档案。字段不含电话、邮箱、内部备注、费率、付款资料或会议数据。
    取消AI平台许可只影响AI接口;下架或编辑后保存草稿会同时停止已选平台返回资料,需人工重新确认发布。接入方对已缓存资料须定期核对可见性,收到404后停止展示并清理。
    Apifox接口文档。响应:200/401/403/404/405/503。

    6.28 精确查询客户联系人资料#

    该客户联系人查询目前仅生产 1.20.4 提供;测试 1.20.4b0 不提供 GET /internal/v1/clients/。两环境原 POST /internal/v1/clients/resolve/ 仍保留。

    接入与授权#

    GET /internal/v1/clients/(无尾斜杠也支持,不重定向)。复用应用 AK/SK HMAC-SHA256,需管理员独立授予 client:read。
    这是管理员授权的全局只读客户联系人资料投影,不是手机号认证,不代表手机持有人身份已验证。不按客户公司或渠道隔离;client:resolve、user:read、conference:read 不授予此能力,不自动扩权。原 POST /internal/v1/clients/resolve/ 的身份解析、认证状态及权限契约保持不变。
    接口只读,不需要 Idempotency-Key,不修改联系人或公司;签名校验仍会占用 Nonce、更新应用最近使用时间/IP。

    参数#

    Query 参数类型规则
    client_contact_idinteger联系人 ID,1–9223372036854775807
    phonestring精确匹配主手机号 phone 或备用手机号 phone1,1–64 字符,无首尾空白
    必须且只能出现一个参数。两项同时出现(即使其中一项为空)、重复同名参数(即使值相同)、未知参数、空参数、无条件请求均 HTTP 400。没有姓名、公司模糊查询或列表能力。
    手机号不做国际区号、空格或格式规范化。URL 中 + 必须编码为 %2B,由公共签名客户端正确编码并签名。同一记录两个手机号同时命中只算一个联系人;多个不同联系人匹配则 409,调用方应改用联系人 ID。
    仅查询联系人和公司 is_deleted=false 的记录;无公司或已删除公司联系人不返回。未标记为 false 的历史删除标志(null)也不纳入查询,与现有联系人过滤口径一致。

    返回示例(虚构数据)#

    HTTP 200:
    {"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、认证状态或其他字段;数据库投影也仅加载五项所需列。
    HTTPcode情况
    400INVALID_REQUEST参数缺失、组合、重复、未知或格式错误
    401authentication_failed缺少凭据、签名错误、过期、重放、应用停用等
    403permission_denied未授予 client:read,或 IP 白名单不允许
    404CONTACT_NOT_FOUND无有效匹配,包含联系人/公司删除或无公司
    405method_not_allowedPOST、PUT、PATCH、DELETE 等不支持的方法
    409AMBIGUOUS_CONTACT手机号命中多个不同有效联系人
    {"code":"CONTACT_NOT_FOUND","message":"未找到有效客户联系人"}
    {"code":"AMBIGUOUS_CONTACT","message":"手机号匹配多个客户联系人,请改用 client_contact_id"}
    错误没有 data、手机号或候选联系人清单。请同时检查 HTTP 状态及响应 code。
    Apifox 沿用根目录公共签名前置操作,仅勾选一个 Query 参数。GET 不填幂等键。

    6.29 按手机号或邮箱精确查询专家基本资料#

    生产 1.20.4、测试 1.20.4b0 均已提供。
    GET /internal/v1/experts/lookup/
    Scope:expert:lookup,管理员须单独显式授权。expert:read、user:read、client:read、client:resolve 均不授予此能力。使用应用 AK/SK 签名,沿用根目录自动签名前置脚本,不需要 Idempotency-Key。
    参数位置类型约束
    phonequerystring,1–64 字符与 email 严格二选一;精确匹配主/备用手机号,不规范化、不拼接区号
    emailqueryemail string,1–64 字符与 phone 严格二选一;对主/备用邮箱做不区分大小写的精确匹配
    拒绝无参数、未知参数、重复参数、空值、首尾空白、同时传入两参数(即使一个为空)以及非法邮箱。URL 中 + 必须编码为 %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_idinteger内部 Candidates.id,不是 AI/目录公开资料的 PublicExpertProfile.id,也不是员工 ID 或客户联系人 ID
    namestring 或 null专家真实姓名;已有空串保留
    companystring 或 null同一条最新工作履历的 org_cn;已有空串保留
    positionstring 或 null同一条最新工作履历的 title;已有空串保留
    仅查询 Candidates.is_deleted=false,不按来源、锁定、可约、派生状态或 AI 公开池过滤,不包含 Galaxy 库。按不同 Candidates.id 计数,不按 original_id 合并;同一专家主/备用字段同时命中仍为一个,不同专家 ID 命中返回歧义错误,不提供候选列表。
    公司与职位取同一条未删除且 category=work 的履历,按 started_at 降序(NULLS LAST)、id 降序确定;最新工作可能已结束,不能当作现任信息。无工作履历时 company、position 同时为 null。只返回上述四字段,不返回联系方式、背景、费用、付款、备注或授权状态;此能力不是手机号/邮箱身份认证。
    HTTPcode说明
    200200唯一命中,data 为四字段对象
    400INVALID_REQUEST查询参数不合法
    401authentication_failed鉴权失败、过期或重放
    403permission_denied缺少独立 Scope 或来源 IP 不允许
    404EXPERT_NOT_FOUND无匹配专家
    405method_not_allowed非支持的请求方法
    409AMBIGUOUS_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":"联系方式匹配多个专家,无法唯一确定"}
    错误无 data、联系方式或候选清单;同时检查 HTTP 状态和响应 code。员工目录 /users/、客户查询 /clients/、AI 公开专家 /experts/ 与本联系方式查询 /experts/lookup/ 的对象、ID 与 Scope 各自独立。

    7 返回对象字段说明#

    以下列出响应中主要业务对象的全部字段。列表与详情引用同一对象;字段“存在”与“非空”是不同概念,nullable 字段可返回 null,文本和数组也可能为空。类型名称对应随附 OpenAPI components。部分字段约束由枚举限定,Task 的状态字段按字符串兼容,不应推断已支付或已完成。

    Meeting#

    字段类型说明
    idinteger当前对象 ID;不同资源的 ID 不可混用。
    consumer_application_idinteger消费应用 ID;指定其他应用时额外需要 meeting:publish。
    managed_by_application_idinteger创建管理应用 ID。
    updated_by_idinteger 或 null最近更新的员工 ID,可为空。
    project_idintegerNDB 项目 ID。
    titlestring标题。
    typeMeetingTypeEnum资源类型,见枚举及本节业务说明。 枚举:["ONLINE", "SUMMARY", "REPORT"]
    tagsJSON标签数组。
    industry_idinteger 或 nullNDB 行业 ID。
    industry_namestring 或 null行业名称。
    backgroundstring背景介绍。
    descriptionstring详情说明。
    outlinestring提纲。
    background_image_urlstring (uri)背景图完整 HTTP(S) URL;不可携带账号密码。
    expertsPublicExpert[]关联的可见公开专家数组;费用接口返回会议专家费用对象。
    starts_atstring (date-time)会议开始时间,ISO 8601;建议显式使用 +08:00。
    ends_atstring (date-time)会议结束时间,必须晚于 starts_at。
    client_charge_hoursstring (decimal)客户收费小时,非负十进制字符串,最多 6 位整数、4 位小数。 格式:"^-?\d{0,6}(?:\.\d{0,4})?$"
    customer_charge_hoursnumber (double)客户收费小时的数值展示字段。
    is_third_partyboolean是否第三方会议,默认 false。
    registration_openboolean当前是否开放参会报名,最终以报名接口校验为准。
    statusStatus1aaEnum资源状态,见枚举及本节业务说明。 枚举:["published", "completed", "cancelled"]
    created_atstring (date-time)创建时间。
    updated_atstring (date-time)更新时间。

    Registration#

    字段类型说明
    idinteger当前对象 ID;不同资源的 ID 不可混用。
    meeting_idinteger会议 ID。
    client_contact_idintegerNDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。
    task_idinteger 或 null关联业务 Task ID;纯纪要预约为 null。
    statusStatusE04Enum资源状态,见枚举及本节业务说明。 枚举:["confirmed", "cancelled", "attended", "no_show", "reserved"]
    attendanceAttendanceEnumpending=待确认,attended=已参会,no_show=未参会。 枚举:["pending", "attended", "no_show"]
    attend_requestedboolean是否曾请求参会;取消后仍可能为 true,应结合 status 判断。
    minutes_requestedboolean是否曾预约纪要。
    task_statusstring 或 null关联 Task 状态。
    charge_statusstring 或 null客户收费状态。
    payment_statusstring 或 null专家支付状态;客户应收 Task 为 not_required。
    created_atstring (date-time)创建时间。

    Expert#

    字段类型说明
    idinteger当前对象 ID;不同资源的 ID 不可混用。
    meeting_idinteger会议 ID。
    expert_idinteger目录接口为公开资料 ID;会议专家接口为内部专家 Candidates ID。
    task_idinteger关联业务 Task ID;纯纪要预约为 null。
    payable_cost_idinteger 或 null关联专家付款成本记录 ID。
    settled_atstring (date-time) 或 null专家费用结算时间;未结算可为空,线上 Schema 未标明 nullable。
    payment_hoursstring (decimal) 或 null专家支付小时,非负十进制字符串,最多 6 位整数、4 位小数。 格式:"^-?\d{0,6}(?:\.\d{0,4})?$"
    unit_pricestring (decimal) 或 null专家支付单价快照,十进制字符串。 格式:"^-?\d{0,8}(?:\.\d{0,2})?$"
    currencystring 或 null费率币种。
    task_statusstring关联 Task 状态。
    charge_statusstring客户收费状态。
    payment_statusstring专家支付状态;客户应收 Task 为 not_required。

    ContentItem#

    字段类型说明
    idinteger当前对象 ID;不同资源的 ID 不可混用。
    meeting_idinteger 或 null会议 ID。
    meeting_titlestring 或 null
    typeContentItemTypeEnum资源类型,见枚举及本节业务说明。 枚举:["minutes", "ai_minutes", "report"]
    titlestring标题。
    summarystring内容摘要。
    bodystring内容正文。
    cover_urlstring (uri)封面 URL。
    industrystring行业名称。
    industry_idintegerNDB 行业 ID。
    tagsJSON标签数组。
    sourceContentItemSourceEnum内容来源 internal 或 third_party。 枚举:["internal", "third_party"]
    attachmentsobject[]公开附件数组;对象白名单字段 name、url、type、size。
    published_atstring (date-time)发布时间。

    PublicExpertProfile#

    字段类型说明
    idinteger当前对象 ID;不同资源的 ID 不可混用。
    display_namestring公开展示姓名。
    display_companystring公开展示公司。
    display_positionstring公开展示职位。
    display_backgroundstring公开展示背景。
    avatar_urlstring (uri)头像 URL,可为空字符串。
    industrystring行业名称。
    industry_idintegerNDB 行业 ID。
    tagsJSON标签数组。
    share_topicsstring可分享话题文本。
    published_atstring (date-time)发布时间。
    meetingsMeeting[]关联的可见会议数组。

    MeetingPublicProfile#

    字段类型说明
    idinteger当前对象 ID;不同资源的 ID 不可混用。
    display_namestring公开展示姓名。
    display_companystring公开展示公司。
    display_positionstring公开展示职位。
    avatar_urlstring头像 URL,可为空字符串。

    PublicExpert#

    字段类型说明
    idinteger当前对象 ID;不同资源的 ID 不可混用。
    namestring名称。
    public_profileMeetingPublicProfile 或 null公开专家资料摘要;其中 id 是公开资料 ID。

    Topic#

    字段类型说明
    idinteger当前对象 ID;不同资源的 ID 不可混用。
    namestring名称。
    backgroundstring背景介绍。
    outlinestring提纲。
    cover_urlstring (uri)封面 URL。
    industrystring行业名称。
    industry_idintegerNDB 行业 ID。
    tagsJSON标签数组。
    published_atstring (date-time)发布时间。
    meetingsMeeting[]关联的可见会议数组。
    contentsContentItem[]关联的已发布内容数组。
    expertsPublicExpertProfile[]关联的可见公开专家数组;费用接口返回会议专家费用对象。

    MyMeeting#

    字段类型说明
    meetingMeeting会议对象。
    registrationRegistration报名或预约对象。

    ContactResolution#

    字段类型说明
    client_contact_idintegerNDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。 最小:1
    requires_reauthenticationboolean匹配手机号是否需要重新认证。
    reauthentication_sincestring (date-time) 或 null要求重新认证的起始时间,可为空。

    MeetingJoinLink#

    字段类型说明
    join_urlstring (uri)入会链接;会议公开 DTO 不包含,只由入会接口返回。

    ExpertInterviewRequest#

    字段类型说明
    idinteger当前对象 ID;不同资源的 ID 不可混用。
    expert_profile_idinteger公开专家资料 ID。
    client_contact_idintegerNDB 客户联系人 ID;由服务端验证身份后绑定,不可直接信任终端输入。
    messagestring约访需求文字,最多 2000 字符;响应顶层 message 为提示文字。
    statusExpertInterviewRequestStatusEnum资源状态,见枚举及本节业务说明。 枚举:["pending", "contacted", "closed", "cancelled"]
    created_atstring (date-time)创建时间。

    8 错误码与处理#

    会议及目录接口常见错误:
    HTTPcode含义与处理
    401authentication_failed缺少请求头、AK/SK 无效、停用/过期、摘要/签名错误、时间戳过期、Nonce 重复或防重放服务不可用;校验时钟和签名,不盲目重放
    403permission_deniedScope 不足或来源 IP 不允许;联系管理员核对授权及服务端出口 IP
    400INVALID_REQUEST参数、时间、金额、关系或状态不合法;也可能缺少业务幂等键
    400INVALID_CONSUMER_APPLICATION指定消费应用不存在、停用、过期或缺少 conference:read
    400CONTACT_NOT_BOUND联系人不存在或没有关联客户公司
    404NOT_FOUND资源不存在、不可见或不在应用访问范围内
    404CONTACT_NOT_FOUND已验证手机号没有匹配的有效客户联系人
    409AMBIGUOUS_CONTACT手机号匹配多个联系人,由业务人员明确绑定
    409NO_ACTIVE_CONTRACT无启用合同,由业务人员补充合同
    409AMBIGUOUS_CONTRACT启用合同不唯一,需要明确 contract_id
    409AMBIGUOUS_PROJECT项目无法唯一确定,需要明确 project_id
    409IDEMPOTENCY_CONFLICT同业务键请求不一致,或试图改变已有报名的项目/合同
    409MEETING_NOT_OPEN会议当前不可报名或尚未开始/已取消不能入会
    409MINUTES_ALREADY_AVAILABLE人工纪要已开放,不能新增纪要预约;改为获取目录内容
    409SETTLEMENT_LOCKED关联 Task 进入财务结算或不可恢复,交业务人员处理
    409JOIN_LINK_UNAVAILABLE会议尚未配置入会链接
    403REGISTRATION_REQUIRED当前联系人没有有效参会报名或关联 Task 已失效
    HTTP 401 示例:
    {"code":"authentication_failed","message":"应用签名校验失败。"}
    HTTP 409 示例:
    {"code":"NO_ACTIVE_CONTRACT","message":"该客户没有启用合同。"}
    错误文案可能变化;解析以 HTTP 状态和 code 为准。400 的字段错误 message 可能是序列化后的对象文本。遇到非 JSON 网关错误、429 或 5xx 时,保留业务键并采用有上限的退避重试;不要记录机密请求头或完整个人信息。

    9 常见联调问题#

    问题检查点
    ping 401AK 是否有效、五个请求头是否齐全、时钟是否秒级、请求体摘要与实际字节是否一致
    GET 签名错误没有 query 时是否保留空行,空 body 是否误签成 {},尾 / 是否一致
    中文或空格签名错误先解码排序再 RFC 3986 编码;空格 %20;Python quote_via=quote;Node 需额外编码 !'()*
    第一次成功,重试 401Nonce 被复用;保留业务 Idempotency-Key,换时间戳和 Nonce
    写请求 409检查是否复用其他操作的业务键、项目/合同是否一致及会议生命周期
    列表为空或详情 404当前应用归属、Scope、发布状态、发布时间、公开专家平台配置
    无法入会不是纯纪要预约、报名有效、Task 有效、已到开始时间、会议未取消且已配置链接
    专家 ID 查不到公开资料 ID 与内部专家 ID 是否混用
    报名收费或专家支付与预期不同由 NDB 合同/专家费率生成财务快照;不能在请求体传任意金额覆盖
    取消后仍有 Task取消报名不自动取消财务 Task,也不自动退款,需走业务财务流程

    10 交付文件与验证范围#

    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 模块补充。示例不是实际生产业务数据,未执行创建会议、报名、取消、结算、数据库或部署操作。

    11 Python 客户端完整源码#

    将以下代码保存为 ndb_client.py;使用方式见第 3 节。

    12 Node.js 客户端完整源码#

    将以下代码保存为 ndb-client.mjs;使用方式见第 3 节。

    6.30 验证员工邮箱密码并返回基本资料#

    POST /internal/v1/users/authenticate/(尾斜杠可省略)。测试1.20.6b0已提供,生产1.20.6已提供。
    Scope:独立 user:authenticate,已有 user:read 不包含验证权限。第三方后端通过 HTTPS 携带同一套五项 AK/SK 签名头调用;只序列化一次 JSON,对实际发送字节计算内容摘要和签名。无 Idempotency-Key。URL 不允许查询参数,密码不得放入 URL、日志或监控。
    参数位置类型必填说明
    usernameJSON bodystring是完整员工邮箱,最多64字符,匹配不区分大小写
    passwordJSON bodystring是员工输入的密码,最多1024字符,不裁剪首尾空白
    请求体仅允许上述两个字段。示例为虚构占位:
    {"username":"employee@example.com","password":"<员工输入的密码>"}
    仅唯一匹配、启用且密码正确的员工可通过。成功 HTTP 200,data直接为单个员工对象(不是items数组),包含 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}}
    HTTPcode含义
    400INVALID_REQUEST / parse_error字段、查询参数或JSON不合法
    401authentication_failed应用签名失败、重复Nonce、应用停用或过期
    401INVALID_CREDENTIALS员工不存在、停用、密码错误或邮箱大小写歧义,统一身份验证失败,不返回data
    403permission_denied缺独立Scope或出口IP不允许
    405method_not_allowed只支持POST
    415unsupported_media_type仅支持application/json
    429throttled达到额度,按Retry-After秒数等待
    503VERIFICATION_UNAVAILABLE共享限流缓存不可用,拒绝验证
    默认每固定自然分钟60次/应用、10次/邮箱(跨应用、大小写变体共享;成功与失败均计数),非滚动窗口。两额度可由环境配置。所有响应带 Cache-Control: no-store。旧原始bcrypt最多72个UTF-8字节,超出拒绝;Django哈希与旧bcrypt均不在此接口升级。此能力由独立应用Scope控制,不改变网页密码登录开关;本次不提供第三方企业微信登录。
    修改于 2026-10-22 13:53:28
    下一页
    Apifox 自动签名调试说明
    Built with