@chatlychat/sdk-node

中文文档
0.9.0发布于 2026/11/06MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 2553

官方Node.js SDK for the Chatly API——打入了REST客户端,webhook签名验证,以及部件身份散列.

中文使用文档
文档目录10 节
  1. 快开始
  2. 客户所能做的
  3. 未包括,为何
  4. 目 录
  5. 正在验证任何东西
  6. 8个表面
  7. 统一 v2 签名
  8. 旋转一个秘密
  9. verifyWebhookSignature (仍在支持)
  10. 关于此寄存器

@chatlychat/sdk-节点

Chatly API 的服务器端客户端. 用 API 密钥认证, 所以它是 用于您的后端, 而不是浏览器, 其中键可以读取 .

pnpm add @chatlychat/sdk-node

快开始

import { ChatlyClient } from '@chatlychat/sdk-node';

const chatly = new ChatlyClient({
  apiKey: process.env.CHATLY_API_KEY!, // ck_live_…
  apiUrl: 'https://api.chatlychat.com', // optional
});

const contacts = await chatly.contacts.list({ limit: 20 });

在下方创建密钥 工作空间 — 开发者 — API 密钥符号显示 一次并仅作为散列储存——如果你失去它,撤销并再铸成一分.

制作 whoami() 你的第一个电话。 它返回密钥所属的工作空间 和它实际持有的瞄准镜, 所以一个误用瞄准镜的密钥 响亮的失败在 集成时间,而不是像一个不相干的人一样迷惑403 生产终点:

const { workspaceId, scopes } = await chatly.whoami();

7个Api-keys的路线接受一个钥匙,从那时起在其中铸造 2026-10-26 (英语) create 拒绝任何范围 调用密钥没有自控, 所以泄露的只读密钥不能升级. 仅 PUT /v1/api-keys/:id/machine-user 继续关闭密钥。 没有的 这里的键入方法可以通过 request(),这需要 headers —— 说 这就是你发送 x-secret-recipient 将新密钥密封 改为公用密钥,而不是以简写形式返回.

客户所能做的

下面的每一种方法都映射到一个接受密钥认证的终点. 范围 仅满足您整合需要的关键; 关键永远不能比 创建时瞄准镜已选中 .

打电话所需范围
chatly.whoami()workspace:read
chatly.contacts.list({ cursor?, limit? })contacts:read
chatly.contacts.upsert({ email, name, … })contacts:write
chatly.conversations.list({ cursor?, limit? })conversations:read
chatly.conversations.messages(conversationId)conversations:read
chatly.conversations.send({ conversationId, body })messages:write
chatly.search.query('refund', { … })search:read
chatly.search.kb('refund')search:read
chatly.events.track({ contactId, name, properties })contacts:write

您随密钥发送的信件被记录为集成发送,而非由 钥匙的创造者, 钥匙的产生者 当他们离开的时候.

未包括,为何

反应和频道/部件配置是故意缺失的. 反应 记录 谁 反应和钥匙不是一个人,所以这些终点需要 注册用户。 频道配置需要一个无法按键的瞄准镜 。 都用过 他们都把403还给每个打电话的人.

目 录

写入接受一等能键, 所以网络失败后重试不进行 重复工作 :

await chatly.withIdempotencyKey('order-4471-refund').contacts.upsert({ … });

正在验证任何东西

verifyChatlySignature 是用来用的。 你告诉它 表面 你们 即将结束,将生体和请求头交给它,然后检查 表面实际使用的构造:

import { verifyChatlySignature } from '@chatlychat/sdk-node';

const result = verifyChatlySignature({
  surface: 'event_webhook',
  body: rawBody, // the EXACT bytes, before JSON.parse
  headers: req.headers,
  secret: process.env.CHATLY_WEBHOOK_SECRET!,
  method: req.method, // see "the unified v2 signature" below
  path: req.url,
});

if (!result.ok) {
  console.warn('rejected', result.reason, result.message);
  return res.status(400).end();
}

传递生体——重排解析 JSON 重排密钥并更改 白空间,所以文摘将不匹配. 在拒绝时, reason 是一个稳定 树枝上的字符串( t)signature_mismatch, (中文(简体) ), timestamp_outside_tolerance, (中文(简体) ), missing_signature_header,(......)和 message 是写成的句子 已打印过。 从来投出.

8个表面

surface页眉已签名字符串t 单位
unified_v2x-chatly-signature-v2: t=…,v1=…<t>.<METHOD>.<path>.<rawBody>秒数
agent_deliveryx-chatly-signature: t=…,v1=…<t>.<rawBody>秒数
event_webhookx-livechat-signature: t=…,v1=…<t>.<rawBody>秒数
ai_tool_callx-chatly-signature: t=…,v1=…<t>.<METHOD>.<path>.<rawBody>秒数
canvas_stepx-chatly-canvas-signature: sha256=… 财务报告和审定财务报表 x-chatly-canvas-ts<ts>.<rawBody>毫秒
customer_cardx-chatly-signature: sha256=… 财务报告和审定财务报表 x-chatly-timestamp<ts>.<rawBody>毫秒
workflow_webhookx-chatly-signature-v2: t=…,v1=…<t>.<rawBody>秒数
workflow_webhook_legacyx-chatly-signature: sha256=…<rawBody> - 没有时间戳无

三个人派来了 x-chatly-signature 并签署三条不同的线条, 这就是为什么 surface 需要而不是从标题中推断:a 验证页眉名称上的密钥可以指向错误 建筑设计,同时看起来完全正确.

ai_tool_call 额外需求 method 财务报告和审定财务报表 path (单位:千美元)pathname + search, (中文(简体) ), 永远不要主机),因为两者都在已签名的字符串内. toleranceSeconds 默认为 300 并且总是在 秒数无论表面的单位 timerstamp使用——转换是此函数的工作,并把它弄错了 用手来检查新鲜度 大约54,000年 并拒绝 一切众生.

偏爱 workflow_webhook 结束 workflow_webhook_legacy。 。 。 . 每个工作流程 webhook 呼叫发送两个信头。 留下的遗物在身体上标出没有 时间戳,所以一个被捕获的请求 永远验证,没有什么可以约束一个 重新播放; verifyChatlySignature 拒绝,除非你通过 allowUnprotectedReplay: true,如果你这样做, 使端点一能.

统一 v2 签名

每个地表都在移动 一个 建筑业:

x-chatly-signature-v2: t=<unix seconds>,v1=<hex>
v1 = HMAC-SHA256(secret, `${t}.${METHOD}.${path}.${rawBody}`)

已经发送 并行 每个表层都有头,所以没有断裂 当发送者迁移时. path 实值 pathname + search 请求全文 来到了... 从来没有计划,也没有东道主。 方法与路径在内 文摘是因为 GET 没有身体标志 "<t>..",这是 与每次会议相同 GET {\fn华文楷体\fs20\bord1\shad1\1che0e0e0\2ch000000}而地表能使出并可以回放出相對相對出相 路径.

过 method 财务报告和审定财务报表 path 打开 每个 呼叫时不需要更改代码 发件人移动 : v2 默认为 'prefer',所以 v2 头被校验 并核查遗留的建筑.

const result = verifyChatlySignature({
  surface: 'customer_card',
  body: rawBody,
  headers: req.headers,
  secret: process.env.CHATLY_CARD_SECRET!,
  method: req.method,
  path: req.url,
  v2: 'prefer', // the default: 'require' once you know the sender has moved
});
// result.surface is 'unified_v2' when the v2 header was the one that verified.

'prefer' 永不退后:如果v2头存在而不验证, 这是拒绝而不是尝试遗产标题的理由。 两个头 同一个秘密,所以一个好的遗产摘要 除了一个坏v2是 篡改或发送错误, 并接受它会隐藏两者。 使用 v2: 'ignore' 将旧行为归结.

一个皱纹,这是我们的: workflow_webhook 已经发送 x-chatly-signature-v2结束 <t>.<rawBody> - 那个标题比 统一基地。 所以在那个地上 两者 无论何时,都接受基地 供应 method 财务报告和审定财务报表 path,以及 result.base (单位:千美元)'body' 或者说 'target'告诉 发件人用的那个.

该值带有 基准标记数字 : t=…,v1=…,b=t 为统一基地, b=b 页:1 <t>.<rawBody>。缺失标记意味着 <t>.<rawBody>,因为 在标记存在之前发送的每个 v2 值就是这个. 校对员看了 缩小其企图,并在拒绝时点出原因——a b=t 工作流程请求无 method编号 :path 实值 missing_request_target,而不是一个 不匹配——但绝不接受比表面允许的更多,因为任何人在 电线可以写出标记.

哪个表面发送 x-chatly-signature-v2 现时: 代理人交付 事件 webhook、客户卡获取和画布/步骤回调,全部 b=t· ; 工作流程动作, b=b. AI工具呼叫尚未发出——他们的遗产 x-chatly-signature 已签名统一字符串, 因此 'prefer' 坠落 通过一个相同的支票,你不会失去任何东西通过 method 财务报告和审定财务报表 path 现在.

如果您终止了多个表面, 请全部验证为 unified_v2。 。 。 . 那个 是一个 v2 标题的已记录路径; 平面名称用于 遗产头。 单一例外,直到发送者移动到 b=t,为 工作流程动作——核实为 workflow_webhook。 。 。 .

旋转一个秘密

旋转的两端都得到支持:

const result = verifyChatlySignature({
  surface: 'agent_delivery',
  body: rawBody,
  headers: req.headers,
  secret: [process.env.CHATLY_SECRET_NEW!, process.env.CHATLY_SECRET_OLD!],
});
if (result.ok) {
  console.log('verified with secret', result.secretIndex); // 0 = the new one
}
  • secret 需要一个阵列. 接受这个新旧秘密 重叠持续; result.secretIndex 你是如何学会的旧的 停止使用.
  • 标题可以包含摘要列表 —— 说 t=…,v1=…,v1=… - 对于发送者 签了两个秘密 任何匹配的验证 它们必须形成良好的结构.

verifyWebhookSignature (仍在支持)

原作"单相"校正. 它处理 event_webhook 仅取 头值而不是头包。 出版、使用、不 离开:

import { verifyWebhookSignature } from '@chatlychat/sdk-node';

const ok = verifyWebhookSignature({
  body: rawBody, // the EXACT bytes, before JSON.parse
  signatureHeader: req.headers['x-livechat-signature'] as string,
  secret: process.env.CHATLY_WEBHOOK_SECRET!,
});

计划是 t=<unix seconds>,v1=<hex>时 v1 hMAC -SHA256 已过 `${t}.${body}`。时间戳在签名的字符串内,所以一个俘虏 一旦外出就停止核查 toleranceSeconds。 。 。 .

这个例子在2026-10-12之前是错的,在三个方面 上面说 payload (现场是: body, (中文(简体) ), signature (这是 signatureHeader和 x-chatly-signature (网络用户) x-livechat-signature) (中文(简体) ). 单位 TypeScript 旧片段是一个编译错误; 在平版 JavaScript 中是 比回去还糟 false,因为核查者分裂 input.signatureHeader 首先,一个缺席的投出一个 TypeError 调出 你的网络操作员.

标题是值得知道的陷阱: x-chatly-signature 这是真实的, 但属于另外四个地表 ——外方代理交货,定制 AI工具呼叫、客户卡和工作流程 fire_webhook 行动——和 每一个都以不同的方式构建其基础字符串。 境外事件 webhoks 是一个使用 x-livechat-signature不共享一个 核查员在检查时不检查施工情况.


关于此寄存器

这是一个 镜像。 。 。 . @chatlychat/sdk-node 由私人独身建筑 其余的 月台的迁移和合同检查现场直播 无法直接合并, 但补丁仍然是获得东西最快的方法 固定了,我们会把它 与归属.

您可以在这里做什么: 读取源代码, 运行测试, 打开一个问题, 或打开一个 PR 并且我们将把diff当作提案.

未镜像 : src/ signition-vectors- public. spec.ts —— 仍然在此重述的类别 与单列波的原作相匹配,这仅仅是其中的一个有意义的主张. 他们 继续跑.

问题: https://github.com/chatlychat/chatly-sdk-node/issues (中文(中国大陆) ) * 文件: https://chatlychat.com/docs (中文(简体) )

版本与发布记录

@chatlychat/sdk-node 共发布 16 个版本,首次发布于 2026/10/13;过去 12 个月发布了 16 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.9.0latest2026/11/063 天前
0.8.02026/10/2713 天前
0.7.42026/10/2614 天前
0.7.32026/10/2614 天前
0.7.12026/10/1723 天前
0.7.02026/10/1723 天前

关于 @chatlychat/sdk-node 的常见问题

@chatlychat/sdk-node 是什么?

官方Node.js SDK for the Chatly API——打入了REST客户端,webhook签名验证,以及部件身份散列.

如何安装 @chatlychat/sdk-node?

在项目目录运行 npm install @chatlychat/sdk-node,或使用 pnpm add / yarn add / bun add。

@chatlychat/sdk-node 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@chatlychat/sdk-node 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@chatlychat/sdk-node 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@chatlychat/sdk-node 可以商用吗?

@chatlychat/sdk-node 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@chatlychat/sdk-node 的下载量有多少?

根据 npm 官方下载统计,@chatlychat/sdk-node 在 2026/10/10 – 2026/11/08 这 30 天内被下载 2,553 次,日均约 85 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@chatlychat/sdk-node 还在维护吗?

最新版本 0.9.0 发布于 2026/11/06(3 天前);至今共发布 16 个版本,其中过去 12 个月发布了 16 个;首次发布于 2026/10/13。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。