# @fastn-ai/sdk 中文文档

规范地址：https://npmcn.com/package/%40fastn-ai/sdk/

版本：0\.5\.1
npm 元数据更新时间：2026-10-31T18:33:19.993Z
中文译文更新时间：2026-11-14T11:34:02.555Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40fastn-ai/sdk
原文对照：https://npmcn.com/package/%40fastn-ai/sdk/?lang=original
项目主页：https://fastn.ai/
源码仓库：https://github.com/fastn-ai/fastn-sdk

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：4 MB，27 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=20
- 运行依赖：1 个
- 首次发布：2026-10-22T18:47:27.742Z
- 最新版本发布：2026-10-31T18:33:19.885Z
- 近 30 天下载量：2378（2026-10-15 至 2026-11-13，npm 官方下载统计）
- 已发布版本数：11（近 12 个月 11 个）

## 中文简介

为Node.js和TypeScript所禁用 SDK:为多租户SaaS和AI代理所嵌入的集成. 您的客户通过一个打入的API将自己的应用程序连接到你的产品中.

## 安装

```sh
npm install @fastn-ai/sdk
```

也可以使用：`pnpm add @fastn-ai/sdk`、`yarn add @fastn-ai/sdk`、`bun add @fastn-ai/sdk`

## README

# @ fastn-ai/ sdk: 为节点

**嵌入的集成 为你的产品和你的AI代理.**

[固态](https://fastn.ai/) 是 B2B SaaS 的嵌入式集成平台. `@fastn-ai/sdk` 是其官方节点.js 和 TypeScript SDK: 在您的产品中添加客户界面集成(CRM,日历,Slack,和1000+多个应用) 通过一个API, 给你的AI代理 与工具相同的整合.

您的客户在您的产品中连接自己的应用程序。 您的后端通过套接字使用这些连接 平台 API,您的代理商称它们为工作空间工具或通过 [禁用 MCP 网关](https://docs.fastn.ai/build/mcp-gateway)。 。 。 .

**为多租户SaaS所建:**

-   **一个钥匙,每个客户.** 用您自己的身份代言每个客户( E)`fastn.customer("acme-42")`); 斋戒的内部 org ids 永远达不到你的代码. 每一次通话都是针对那个客户 以及属于他的账户或监视码 所以一个客户的数据 永远不会泄露到另一个客户的.
-   **每位顾客都有自己的账户.** 发送一个设置链接, 客户连接 HubSpot, Google 历,斯克等. 代表证留在Fainten的金库里,每个客户隔离,自动刷新.
-   **每个应用程序有几个账户.** 一个客户可以连接两个Slack工作空间或两个日历;每个呼叫一个 `connectionId`。 。 。 .
-   **一个API跨供应商.** `customer.crm` 财务报告和审定财务报表 `customer.calendar` 工作方式与客户关系管理或日历方式相同 客户连接; 提供者是从他们的连接中选择的 .
-   **安全追溯和追踪.** `idempotencyKey` 使写作安全可重试 `correlationId` 让你问 后因求取所施斋戒`customer.callLog(...)`) (中文(简体) ).
-   **受受想行识.** 基于角色的接入控制,审计日志,以及SOC 2 二型平台上的每个客户隔离.

**当 :**

-   您的客户要求整合 您的团队不能一个接一个地建设和维护;
-   每个客户都需要与自己账户连接并配置到自己字段的相同整合;
-   你想要一个集成 服务你的产品,你的客户, 你的AI代理;
-   您需要每个客户的隔离、 审计记录和SOC 2 进行安全审查.

**软件包 :**

-   节点20+(内置取取取),无害环境管理和普通JS,全类型. 一次性的依赖性`json-schema-to-typescript`)为 仅由 `fastn-sdk-tools` 代码生成器.
-   \* 在19个地区开展461起行动`orgs`, (中文(简体) ), `embed`, (中文(简体) ), `connections`, (中文(简体) ), `unified`, (中文(简体) ), `events`, (中文(简体) ), `workflows`,),每个方法 操作,其名称与API文档和Fastn Workspace工具中的操作完全相同。 平台行政管理 伙伴键不能调用的路径被故意忽略.
-   客户上下文隐藏了 faten 的内部 org 标识 : 您只使用过您给 saten 的 ID .
-   事件签名验证, 重试, 键入错误, 标记 .

## 安装

```bash
npm install @fastn-ai/sdk
```

从平台获取 API 密钥 [丝网仪表板](https://app.fastn.dev/)。客户端不读取环境 变量本身:将密钥传入.

```ts
import { FastnClient } from "@fastn-ai/sdk";             // ESM
// const { FastnClient } = require("@fastn-ai/sdk");     // CommonJS
```

## 60秒旅行

```ts
import { Apps, Categories, Entities, EventTypes, FastnClient, HubSpotEvents } from "@fastn-ai/sdk";

const fastn = new FastnClient({ apiKey: process.env.FASTN_API_KEY! });   // https://api.fastn.dev

// 1. Register a customer under your account, using YOUR id for them.
const customer = fastn.customer("acme-42");
await customer.register({ name: "Acme Dental" });              // idempotent: returns the existing org on repeat

// 2. Give them a link to connect their tools (Google Calendar, HubSpot, ...), by connector slug.
const link = await customer.connect(Apps.googleCalendar);
console.log(link.url);                                         // send this to the customer

// 3. Typed methods on whatever the customer connected: the provider is picked from their connections.
const booked = await customer.calendar.book(
  { title: "Intro call", start_time: "2026-11-03T15:00:00Z", end_time: "2026-11-03T15:30:00Z", timezone: "Europe/London", attendee_email: "jane@example.com" },
  { idempotencyKey: "booking-123", correlationId: "req-abc" },  // safe to retry; traceable later
);
console.log(booked.id, booked.provider, booked.data.web_url);

await customer.calendar.reschedule(booked.id, { start_time: "2026-11-03T16:00:00Z", end_time: "2026-11-03T16:30:00Z" });
await customer.calendar.cancel(booked.id, { idempotencyKey: "cancel-123" });

const { records } = await customer.crm.contacts.find({ email: "jane@example.com" }); // one page (the search route has no cursor); list() pages
const contact = records[0] ?? await customer.crm.contacts.create({ first_name: "Jane", last_name: "Doe", email: "jane@example.com" });
await customer.crm.notes.add({ body: "Booked an intro call", parent_id: contact.id, parent_type: Entities.contact });

// 4. What did fastn do for my request id?
await customer.callLog("req-abc");
```

## 在您的产品中嵌入套件( Claude 和其他 AI 编码助理的指南)

将客户界面集成到一个带有快餐的SaaS应用程序中的步骤. 使用以下确切名称; 不发明 道具或终点.

1.  **安装并获得密钥 .** `npm install @fastn-ai/sdk`,然后在 [丝网仪表板](https://app.fastn.dev/) 传为 `apiKey`。 。 。 .
    
2.  **用自己的身份证登记每个客户** (后端):
    
    ```ts
    const fastn = new FastnClient({ apiKey: process.env.FASTN_API_KEY! });
    const customer = fastn.customer(account.id);              // your id for this customer
    await customer.register({ name: account.name });          // idempotent
    ```
    
3.  **让客户连接他们的应用.** 或发送主机设置链接, 或显示您用户界面中嵌入的部件 :
    
    ```ts
    const link = await customer.connect(Apps.hubspot);           // hosted page: redirect the customer to link.url
    const token = await customer.embedToken();                // or: a short-lived token for the in-app widget
    ```
    
    在前端,部件是 [`@fastn-ai/embed`](https://www.npmjs.com/package/@fastn-ai/embed) 软件包 (单位:千美元)`FastnProvider` 与 `FastnHub` 或者说 `FastnConnectCard` 从 `@fastn-ai/embed/react`,或主机脚本标记). 从仪表板的嵌入式标签上复制精确片段. 见 [嵌入文件](https://docs.fastn.ai/embed/embedding)。 。 。 .
    
4.  **使用客户连接** 从您的后端 : `customer.crm.contacts.find(...)`, (中文(简体) ), `customer.calendar.book(...)`,或 `customer.runAction({ connector, action, input })` 任何应用动作.
    
5.  **对更改的反应**数字 : `fastn.webhooks.create(...)` 一次为你的账户, `customer.watch(app, events)` 百分比 客户,并核查交货情况 `parseEvent(secret, headers, rawBody)`。 。 。 .
    
6.  **给你的人工智能特工 同样的整合**数字 : [工作空间工具](https://npmcn.com/package/%40fastn-ai/sdk/#readme-workspace-tools-run-anything-your-workspace-has-turned-on) 或连接 Claude、Cursor 或 MCP 客户端到 [禁用 MCP 网关](https://docs.fastn.ai/build/mcp-gateway)。 。 。 .
    

定价是每个客户的连接, 免费计划开始: 见 [斋戒/定价](https://fastn.ai/pricing)。 。 。 . 用于LLMS的可机器读取的固件摘要在 [subn.ai/llms.txt](https://fastn.ai/llms.txt)。 。 。 .

## 配置

```ts
new FastnClient({
  apiKey,                          // required: platform API key, sent as x-api-key
  baseUrl,                         // default https://api.fastn.dev; https://api.fastn-test.dev for development
  timeoutMs,                       // per request, default 60000
  retries,                         // GET and idempotent calls on 429/502/503/504 and network errors, default 2
  defaults,                        // options for every call, e.g. { customer: { ref: "acme-42" } }
  onRequest,                       // (log: RequestLog) => void, after every HTTP attempt
  fetch,                           // a fetch implementation, default globalThis.fetch
  userAgent,
  tools,                           // { key, url, timeoutMs }: your fastn Connect workspace, enables fastn.tools
});
```

## 命名的应用程序、 类别和事件

`Apps`, (中文(简体) ), `Categories`, (中文(简体) ), `Entities`, (中文(简体) ), `HubSpotEvents`, (中文(简体) ), `EventTypes` 财务报告和审定财务报表 `UnifiedActions` 将统一中的每个应用程序命名 目录,每个类别和实体, HubSpot 的更改事件, 以及您的 Webhook 接收的事件, 所以调用由您的编辑完成并检查, 而不是按字符串键 : `customer.connect(Apps.googleCalendar)`, (中文(简体) ), `customer.watch(Apps.hubspot, [HubSpotEvents.contactCreated])`, (中文(简体) ), `fastn.catalog.fields(Categories.crm, Entities.contact)`, (中文(简体) ), `{ provider: Apps.hubspot }`错误成员 (单位:千美元)`Apps.googleCalender`, (中文(简体) ), `HubSpotEvents.contactCraeted`)不编译。 普通字符串仍然被接受, 而不是 选中 : `watch` 签名前拒绝未知事件名称( n)`FastnApiError` 400个 `EVENT_NOT_FOUND`,带有有效的 名称),并缺少名称(`undefined` 从 Plain JavaScript 中的错误成员中扔出一个 `TypeError` 命名调用。 每个值是 API 的确切字符串 使用,所以已有的字符串呼叫继续工作. 列表为0.5.0生产的统一目录; app, 类别或实体。 下面的片段从 `@fastn-ai/sdk`。 。 。 .

## 日历和客户关系管理,已键入

`customer.calendar` 财务报告和审定财务报表 `customer.crm` 是带有命名字段的统一 API: 每种方法都使用 TypeScript 界面(目录本身的字段名称, `start_time`, (中文(简体) ), `first_name`; ; ; ; ; `Date` 值作为 ISO 字符串发送)和 答题 `{ id, provider, data, warnings? }` 或页面 `{ records, nextCursor, hasMore }`提供商是 客户已连接该实体: 没有连接的提供者回答 404 `NO_CONNECTED_PROVIDER` (给他们一个设置) 页:1 `PROVIDER_AMBIGUOUS` (通过) `{ provider }`) (中文(简体) ). `warnings` 列出提供者不使用的字段 地图因此被丢弃。 每一个方法 `{ provider?, connectionId?, idempotencyKey?, correlationId?, ... }` 最后一个.

| 方法 | 在下面 |
| --- | --- |
| `calendar.freeSlots({ start_time, end_time, timezone?, slot_minutes? })` | 时间安排/可用性; 答案 `busy`, (中文(简体) ), `free`,以及 `slots` 该长度 |
| `calendar.book(meeting)`, (中文(简体) ), `get(id)`, (中文(简体) ), `find({ start_time, end_time })`, (中文(简体) ), `list({ page_size, cursor })`, (中文(简体) ), `reschedule(id, { start_time, end_time, duration_minutes? })`, (中文(简体) ), `cancel(id)` | 时间安排/会议 |
| `crm.contacts.create / get / find({ email, phone, first_name, last_name }) / list / update / delete` | 中心/联系人 |
| `crm.notes.add({ body, parent_id, parent_type })`, (中文(简体) ), `create`, (中文(简体) ), `get`, (中文(简体) ), `find`, (中文(简体) ), `list`, (中文(简体) ), `update`, (中文(简体) ), `delete` | 缩略语/注解(`created_at` 默认为现在) |
| `crm.tasks.add({ subject, due_date, status, ... })`, (中文(简体) ), `create`, (中文(简体) ), `get`, (中文(简体) ), `find`, (中文(简体) ), `list`, (中文(简体) ), `update`, (中文(简体) ), `delete` | crm/任务 |
| `crm.deals.create({ name, amount, stage, ... })`, (中文(简体) ), `get`, (中文(简体) ), `find`, (中文(简体) ), `list`, (中文(简体) ), `update`, (中文(简体) ), `moveStage(id, stage)`, (中文(简体) ), `delete`, (中文(简体) ), `stages()` | 核心/机会、核心/阶段 |

他们没有掩盖的只是一通电话: `customer.records({ category, entity, provider })` 带走任何实体 在目录中包含未键入的输入( e)`create`, (中文(简体) ), `get`, (中文(简体) ), `list`, (中文(简体) ), `update`, (中文(简体) ), `delete`附加时 `search(filters)` 财务报告和审定财务报表 `providers()`),以及 `customer.runAction(...)` 运行连接器自己的动作.

```ts
// The catalog: which categories and entities exist, the fields each takes, which providers a customer connected.
const categories = await fastn.catalog.categories();                 // [{ slug: "crm", entities: [{ slug: "contact", operations, createFields }] }]
const fields = await fastn.catalog.fields(Categories.crm, Entities.contact);         // [{ field: "email", type: "string", required: false }, ...]
const providers = await customer.catalog.providers(Categories.crm, Entities.contact); // [{ connectorSlug: "hubspot", connected: true, operations: [...] }]
```

每个区域都直接在客户端上,并有输入输入. 伙伴们住在 `orgs`, (中文(简体) ), `embed`, (中文(简体) ), `connections`, (中文(简体) ), `unified`, (中文(简体) ), `events` 财务报告和审定财务报表 `workflows`平台管理区域(admin,平台配置,支持)和后端唯一路径(OAuth召回,证书读取,员工批准)不生成:一个伙伴键不能调用它们,而把它们放出会让SDK承诺保持稳定小的表面. 发电机的 `HIDDEN_TAGS` 编号 : `PUBLIC_INTERNAL` 列表中 `scripts/generate.ts` 是唯一一个统治的地方.

```ts
await fastn.orgs.listOrgs({ type: OrgTypes.endOrg });
await fastn.connections.listConnections({ endOrgId: await customer.id() });
await fastn.events.listEventSubscriptions();
await fastn.embed.getSetupLink({ id: "stp_..." });
await fastn.orgs.getTenant({ id: "..." });                     // every operation is a typed method on its area
await fastn.me();                                               // who this key is: actor, role, org, parentOrg
```

## 客户身份证,解释一次

使用 `fastn.customer(ref)` (或 `customer` 选项),没有其他。 原始的 API 名称是同一客户 每个操作不同;生成的输入字段仍然存在,但它们是原始的API,并将是 在站台一侧重新命名. 给客户的限定电话需要一个多租户伙伴API键;该平台 拒绝单租户密钥上的客户头(此处不由测试行使).

| 在API 文档中 | 这是什么 | 在这个SDK里 |
| --- | --- | --- |
| `orgId` (创造十大身体) | 你为客户选择的ID | `fastn.customer(ref)` |
| `externalRef`, (中文(简体) ), `endOrgRef`, (中文(简体) ), `x-end-org-ref` | 同一编号,在其他名称下 | 填给你的 |
| `endOrgId`, (中文(简体) ), `id` (创造Tenant回答), `x-end-org-id` | 瑞根自己的客户身份 | `await customer.id()` (被夹住) |

`customer.find()` 返回客户端的曲线行(或 `undefined` 在禁食者不知不觉的时候. `customer.register()`, (中文(简体) ), `connect(app)`, (中文(简体) ), `links`, (中文(简体) ), `watch()`, (中文(简体) ), `disconnect()`, (中文(简体) ), `renameAccount()`, (中文(简体) ), `update()`, (中文(简体) ), `callLog()`, (中文(简体) ), `setupLink()`, (中文(简体) ), `embedToken()`, (中文(简体) ), `connectWithCredentials()`, (中文(简体) ), `connections()`, (中文(简体) ), `get()`, (中文(简体) ), `remove()`, (中文(简体) ), `calendar`, (中文(简体) ), `crm` 财务报告和审定财务报表 `records(...)` 只要API坚持 所有人就接受回授 解决Laten的ID 寻找是 仅限于在自己的类人之下 所以一个比你的账户看得更清楚的密钥 其他人的客户; 解析的id是缓存每个客户.

`customer.api.<area>.<operation>()` 经营客户的任何业务。 它发送x-end-org-ref,在路线上 将客户带入身体(`endOrgId` 或者说 `externalRef`: OAuth 启动、存储连接、事件 订阅,秘密,设置链接,... ,填补字段。 平台只在统一记录上读取标题 和工作流程执行路径;没有正文字段,这些呼叫会默默地作为你自己的轨道运行.

```ts
// A setup link by app: the account's widget for that connector is found for you (several: pass widgetId).
const link = await customer.connect(Apps.hubspot, { connectionName: "Main CRM", redirectUrl: "https://app.acme.com/connected" });
redirect(link.url);                                                   // then customer.links.get(link.setupId) / links.cancel(...)

// Or start OAuth directly, without a widget:
const { data } = await customer.connect({ connectorId: Apps.googleCalendar, connectionName: "Google Calendar", returnUrl: "https://app.acme.com/connected" });
redirect(data.authorizationUrl);                                      // the connection lands on the customer org

// Typed-in credentials (API key, basic auth): the fields come from the connector's auth method. The platform checks
// them; an incomplete set answers 400 CREDENTIALS_INCOMPLETE with the missing names (err.body.missing).
const fields = await customer.authFields("acme-crm");                 // { names, required, schema, authMethodId }
await customer.connectWithCredentials({ connectorId: "acme-crm", credentials: { apiKey: "..." }, name: "Acme CRM" });
```

```ts
// Changes at an app, sent to your webhook as connector.event / unified.event: watch them per customer.
const accountId = "...";                                              // one of the customer's accounts, from customer.connections()
const w = await customer.watch(Apps.hubspot, [HubSpotEvents.contactCreated, HubSpotEvents.dealStageChanged], { accountId });
// HubSpotEvents.dealStageChanged delivers every deal property change: keep stage moves with propertyName === "dealstage".
await customer.watches(Apps.hubspot);                                 // [{ id, app, events, status }]
await customer.unwatch(Apps.hubspot);                                 // or unwatch(w.id)
await customer.watchableEvents(Apps.hubspot);                         // the app's event names you can watch

await customer.disconnect(accountId);                                 // the customer gets connection.revoked
await customer.renameAccount(accountId, "Front desk calendar");
await customer.update({ name: "Acme Dental Ltd" });                   // or { status: "suspended" }
await customer.callLog("req-abc");                                    // what fastn did for your request id

// Your webhook, once for the whole account.
const hook = await fastn.webhooks.create({ url: "https://app.acme.com/fastn", eventTypes: [EventTypes.connectionConnected, EventTypes.setupLinkCompleted, EventTypes.connectorEvent, EventTypes.unifiedEvent] });
hook.secret                                                           // shown once: the signing secret for parseEvent
await fastn.webhooks.test(hook.id); await fastn.webhooks.deliveries(hook.id); await fastn.webhooks.rotateSecret(hook.id);
```

```ts
// Anything the unified API does not cover: run the connector's own action with the customer's connection.
const r = await customer.runAction({ connector: Apps.hubspot, action: "updateDeal", input: { dealId, properties: { dealstage: "qualifiedtobuy" } } });
r.data.response                                                       // the provider's answer
```

偏爱 `setupLink()` 代表证:santn的主页收集到,所以他们从不通过你的后端. 对于 自定义输入以外的认证类型构成平台可以将证书存储在不同的固定字段名下 从Auth方法的合同中;这是一个正在跟踪的平台限制,而不是SDK能看到的.

## 答复和错误

答案正按 REST API 发送时返回( 通常是) `{ data: ... }`; 统一记录为 `{ id, provider, data }`)),所以SDK同意了1:1与REST文件及邮递员收藏. 输入光谱的位置 描述答案, `Record<string, any>` 否则.

非-2xx 答案抛出 `FastnApiError` 与 `status`, (中文(简体) ), `code` (例如:. `NOT_FOUND`, (中文(简体) ), `VALIDATION_ERROR`, (中文(简体) ), `NO_CONNECTED_PROVIDER`, (中文(简体) ), `OPERATION_NOT_SUPPORTED`, (中文(简体) ), `PROVIDER_AMBIGUOUS`, (中文(简体) ), `message`, (中文(简体) ), `details`, (中文(简体) ), `body` 财务报告和审定财务报表 `requestId` (请斋戒的时候引用它),再加上援助者 `isNotFound`, (中文(简体) ), `isConflict`, (中文(简体) ), `isRateLimited`, (中文(简体) ), `isAuth` 财务报告和审定财务报表 `isValidation`网络失败 `FastnNetworkError`。 。 。 . `GET` 电话于429/502/503/504号重审(违约2起重审,尊重 `Retry-After`) (中文(简体) ). 只有当 它携带一个 `idempotencyKey` **财务报告和审定财务报表** 平台将其操作复制(创建、更新统一记录) 并删除,工作流程执行;每种方法在其文件中都如此表示). 所有其它的写作都从未重考过,所以丢失了 答案不能使其行动两次.

```ts
try { await fastn.orgs.getTenant({ id }); }
catch (e) { if (e instanceof FastnApiError && e.isNotFound) ... }
```

## 按呼选项

每一种方法都采用可选的第二个参数:

```ts
{ idempotencyKey, correlationId, customer, installationId, targetOrg, headers, extraBody, extraQuery, timeoutMs, retries, signal }
```

`extraBody` 编号 : `extraQuery` 发送 SDK 尚未知道的字段( 在 SDK 赶上之前是一个新的 API 字段); 它们是 以给定的方式通过,而不经过验证.

`customer` 实值 `{ ref: "acme-42" }` (你的号码)或 `{ id: "<fastn org id>" }`。 。 。 . `new FastnClient({ defaults: { customer: { ref: "acme-42" } } })` 对每个呼叫都应用选项.

## 工作空间工具: 运行您工作空间打开的任何工具

上方的站台API是一扇门. 另一种是您的连接工作空间( 连接. fastn. dev > Tools): 每个连接器 在那里切换,Google日历,HubSpot,Slack,快取工作空间本身,成为SDK可以列出和运行的工具. SDK中没有任何东西与连接器相连;在工作空间打开一个,它就出现了.

```ts
import { Apps, ToolsClient } from "@fastn-ai/sdk";        // or new FastnClient({ apiKey, tools: { key, url } }).tools

const connect = new ToolsClient({ key: process.env.FASTN_TOOLS_KEY!, url: "https://mcp.fastn.dev/<workspace>" });
const tools = await connect.tools();                           // every tool your workspace has switched on, with its input schema
const cal = await connect.toolsOf(Apps.googleCalendar);        // one connector's tools

// Call them as typed methods, generated from your workspace (next section): no tool names typed by hand.
// tools.customer("acme-42").googleCalendar.listEvents({ calendarId: "primary", timeMin: new Date().toISOString() })
```

-   工作空间密钥是不同于平台API密钥的证书. 在连接.fastn.dev中从设置 > API密钥读取.
-   `customer(ref)` 发送 `X-Org-Id: ref`授权的密钥需要每一次呼叫(400次,否则);设定一次 `defaults: { customer: { ref } }` 当一个客户为一个客户服务.
-   `userId` 当工作空间像每个人一样运行时,需要获得X-User-Id的同意.
-   失败投出 `ToolError` 与 `kind` http" (出道),"rpc"(JSON-RPC,例如未知工具),"工具"(工具运行) 并回答错误)或"auth"(应用程序尚未为这名客户连接),加 `status`, (中文(简体) ), `code`, (中文(简体) ), `tool`, (中文(简体) ), `connector`网关的信息 和帮助者 `isUnknownTool` 财务报告和审定财务报表 `isAuth`. 对于"Auth", `e.isConnectionRequired` 是真的,还有 `e.authorizeUrl` 就是把顾客送到哪里去, 因此代理可以要求用户在运行时连接而不是失败.
-   在"一个共享账户"模式中,每一次通话都作为同一个账户运行,无论你叫什么客户. 每个客户账户 需要工作空间中的“每个客户端”模式.
-   顾客名一出. Fastn Workspace 工具为客户行为( 统一记录) 将其作为 `endOrgRef` 参数,以及 `customer(ref)` 填充每个工具的输入计划,从一个 工具/列表,每个工作空间(由 `customer()` 克隆人,保存了10分钟. 一个 `endOrgRef` 或者说 `endOrgId` 你输了就赢了; `customerArg: false` 在客户端 关闭填充。 其他连接器的工具是左侧的 单独:客户通过X-Org-Id联系他们. 打电话 `await connect.tools()` 第一次通话时一次 不得支付列名费用.
-   客户姓名:写 `orgId` 在 Fastn 工作空间工具的参数中。 工具拼写的地方 `endOrgId` 或者说 `end_org_id` (没有) `orgId` sDK在拼写下传递值 所以 代码从不带旧名;旧名下通过的一个值是原样.
-   Fastn Workspace 工具的解答和解析事件无 fastn 的内部客户ID密钥返回 (单位:千美元)`endOrgId`, (中文(简体) ), `end_org_id`: 你看到的唯一的客户id是您选择的(`orgId` 编号 : `tenantRef`) (中文(简体) ). `r.text` 保留 原始答案; `parseEvent(..., { internalIds: true })` 将id保存在一个事件.

### 您工作空间的打入方法 : `fastn-sdk-tools`

工具名作为字符串工作, 但是您的编辑器无法检查它们 。 生成器将您工作空间的工具列表变成一个 TypeScript 模块,每个连接器有类,每个工具有方法,每个输入都从工具的图中键入:

从一个有 `@fastn-ai/sdk` 已安装( 此包中的指令舰; 没有单独的 `fastn-sdk-tools` npm 上的软件包。 没有本地安装, 使用 `npx -p @fastn-ai/sdk fastn-sdk-tools ...`。 。 。 .

```sh
# once, and again whenever the workspace changes (commit the file)
export FASTN_TOOLS_KEY=...                                        # the workspace key; it never ends up in the file
npx fastn-sdk-tools --url https://mcp.fastn.dev/<workspace> --out src/fastn-tools.ts
npx fastn-sdk-tools --url https://mcp.fastn.dev/<workspace> --out src/fastn-tools.ts --check   # CI: exit 1 on drift
npx fastn-sdk-tools --import ./my-client.js ...                    # optional: module to import the client from
```

```ts
import { ToolsClient } from "@fastn-ai/sdk";
import { createTools } from "./fastn-tools.js";

const tools = createTools(new ToolsClient({ key: process.env.FASTN_TOOLS_KEY!, url: "https://mcp.fastn.dev/<workspace>" }));
// or createTools(fastn) with a FastnClient created with tools: { key, url }

const acme = tools.customer("acme-42");                                       // X-Org-Id on every call, endOrgRef filled where a tool takes it
const cals = await acme.googleCalendar.listCalendars({});                     // tools.<connector>.<tool>(args, opts?)
const created = await acme.hubspot.createContact({ email: "jane@example.com", firstname: "Jane" });   // args typed from the schema
const cats = await tools.fastnPlatform.listUnifiedCategories();               // a tool with no inputs takes no argument
created.data                                                                  // ToolResult, as from call(); ToolError on failure
```

-   `--url` + 键 `--key` (或 `FASTN_TOOLS_URL` 编号 : `FASTN_TOOLS_KEY`(b) 只有《国际清单》读取这些清单); `--from tools-list.json` 生成 从已保存的工具/列表中下线(相同的列表给出相同的文件). `--customer <ref>` 获取列表为 顾客. 信头记录url,客户和工具计数,从不记录密钥.
-   模块导出 `createTools`, (中文(简体) ), `Tools`,每个连接器一个类别(`GoogleCalendarTools`),每个输入接口 工具 (`GoogleCalendarListEventsInput`),该工具发布一个 `outputSchema` (因为答案是) `unknown`),以及 `TOOL_NAMES`。没有连接器前缀的工具(`skill`, (中文(简体) ), `feedback`)是根上的方法.
-   名称是标识符`google-calendar` - > (中文) `googleCalendar`, (中文(简体) ), `create-contact` - > (中文) `createContact`); 之后发生冲突 获得名称的变体(`create_contact`, (中文(简体) ), `createContactTool`) (中文(简体) ). 属性名称保留为图解 (必要时引用)。 一个工具,它的图谋 没有提到一个字段类型 `unknown`; 无对象 已声明属性为 `Record<string, unknown>`。 。 。 .
-   `tools.client` 这是 `ToolsClient` 在方法下,对于一个工具,文件尚不知道; `client.rpc(method, params)` 向工作区发送其他JSON -RPC的电话.
-   程序用途 : `import { generateToolsModule } from "@fastn-ai/sdk/codegen"`。计划到类型的步骤是 `json-schema-to-typescript`,该软件包的一次性运行依赖性(CLI运行于已安装的软件包,所以 不能是devDependency;它只能由生成器装入,从不由客户端装入.

## 事件(网点)

```ts
import { Apps, EventTypes, parseEvent, verifyEventSignature } from "@fastn-ai/sdk";

// Express: app.post("/fastn/events", express.raw({ type: "application/json" }), (req, res) => {
const event = parseEvent(process.env.FASTN_EVENT_SECRET!, req.headers, req.body);   // throws on a bad signature
// event.id is stable across retries: drop repeats by id.
switch (event.type) {
  case EventTypes.connectionConnected: if (event.app === Apps.hubspot) { /* start a watch */ } break;
  case EventTypes.setupLinkCompleted: /* event.connections: app -> account id */ break;
  case EventTypes.unifiedEvent: /* event.action: UnifiedActions.created | updated | deleted */ break;
}
```

签名是 `sha256=HMAC-SHA256(secret, "<X-Fastn-Timestamp>.<raw body>")`; 交货时间超过5分钟 被拒绝(`{ toleranceSeconds }`,0禁用检查). 总是通过生体,从不重复序列化物体. `parseEvent` 抛出平原 `Error` 在一个糟糕的签名. `verifyEventSignature` 回答一个布尔代替, `readEventHeaders` 读取粘接头,和 `signEventBody` 以同样的方式(用于测试)签名.

## 倾斜

```ts
import { paginate } from "@fastn-ai/sdk";
for await (const ev of paginate((i) => fastn.events.listEvents(i), { outcome: EventOutcomes.sentToDlq }, { pageSize: 100 })) ...
```

工程为 `limit`编号 :`offset` 列表和光标列表; 在短页、 丢失的光标或忽略呼号的列表上停止.

## 发展

```bash
npm run generate     # spec/openapi-*.json -> src/generated (ops, types, api)
npm test             # unit tests with a mocked fetch
FASTN_API_KEY=... FASTN_TEST_CUSTOMER=... npm run test:live   # live run on api.fastn-test.dev (creates and removes test data)
# FASTN_BASE_URL=https://api.fastn.dev LIVE_PROD=1 ... runs the same suite on production
# FASTN_API_KEY=... npx tsx scripts/sweep/run.ts   # calls every published operation once on dev and writes a per-operation report
npm run build        # dist/ (esm + cjs + d.ts)
npm run spec:refresh -- /path/to/fastn-platform   # pull a newer spec from a platform checkout
```

`spec/SOURCE.md` 记录该光谱来自哪个平台。 与SDK曝光相比 461在平台-行政管理和后端-唯一线路被隐藏后仍保留.

### 保持兼容

-   手写层`FastnClient`, (中文(简体) ), `customer(...)`, (中文(简体) ), `records(...)`, (中文(简体) ), `ToolsClient`, (中文(简体) ), `parseEvent`, (中文(简体) ), `paginate`, (中文(简体) ), 错误类)跟随 semver : 仅在主要版本中打破更改. 直到1.0,他们仍然可以降落在一个 并列在变换组中.
-   生成的方法与REST API 1:1. `spec/surface.lock.json` 用输入记录每个操作 键(每根线都上线,是否需要)及其输出字段(路径、结构类型, 是否始终存在;没有说明). `npm run generate` 拒绝删除操作、重命名或 移动一个输入,使一个需要的可选输入,添加一个需要的输入,删除或重打输出字段,或 停止保证一个, 除非运行 `--accept-breaking`,它与一个主要的版本起伏。 新业务, 新可选输入,新输出字段和描述编辑通过. `npm run generate:check -- --spec=<file>` 报告在不写任何东西的情况下(在休息时间1出局),CI和尝试刷新时会改变什么.
-   所有东西都放在下面 `unstable` (电线表) `OPS`, (中文(简体) ), `FetchTransport`)没有兼容承诺.

## 释放

1.  弹出 `version` 内 `node/package.json` 更新 `node/CHANGELOG.md` 在公关.
2.  合并后,标签 `main` 并按下标签:
    
    ```bash
    git tag node/v<version> && git push origin node/v<version>
    ```
    
3.  这个 `Publish Node SDK` 工作流程检查标签匹配 `package.json`,运行检查,运行 `npm stage publish`它使用 `NPM_TOKEN` 秘密( 仅限舞台的符号) `npm` GitHub 环境.
4.  维护者打开 npmjs.com > 阶段包,以2FA审查版本并批准. 只有那时它才能被安装.

## 财务问题

**什么是丝坦?** B2B SaaS的嵌入式集成平台. 您的客户连接自己的应用程序( HubSpot, Google Calendar, 和1000+)在你的产品内部, 你的代码和AI代理通过一个API使用这些连接.

**我该如何在我的节点J或TypeScript应用中加入客户界面集成??** 安装 `@fastn-ai/sdk`,将每个客户注册到 `fastn.customer(yourId).register(...)`,让他们连接应用程序 带有设置链接( n)`customer.connect(app)`)或为: `@fastn-ai/embed` 部件,然后调用 `customer.crm`, (中文(简体) ), `customer.calendar`,或 `customer.runAction(...)`。见 [在你的产品中嵌入了软糖](https://npmcn.com/package/%40fastn-ai/sdk/#readme-embed-fastn-in-your-product-guide-for-claude-and-other-ai-coding-assistants)。 。 。 .

**套接字支持多租户应用程序吗?** 对 每通电话都以一个客户为范围,由您本人的身份证发出;每个客户的证书都保存并刷新 客户;客户可以连接一个应用程序的多个账户.

**Claude这样的AI特工能使用自制融合吗?** 是: 作为此 SDK 的工作空间工具( S)`ToolsClient`键入 `fastn-sdk-tools`),或通过 [禁用 MCP 网关](https://docs.fastn.ai/build/mcp-gateway) claude、Cursor或任何MCP客户端.

**有Python SDK吗?** 对: [`fastn-ai`](https://pypi.org/project/fastn-ai/) (单位:千美元)`pip install fastn-ai`) (中文(简体) ). 内容 `fastn.platform` 客户端拥有 与这个软件包的平台客户端相同的表面,它加入了呼吁OpenAI,Anthropic,双子座和Bedrock的工具, 流动,和CLI。 此软件包的工作空间工具( NAME OF TRANSLATORS)`ToolsClient`, (中文(简体) ), `fastn-sdk-tools`)仅为节点.

## 许可证

麻省理工学院

## 常见问题

### @fastn-ai/sdk 是什么？

为Node\.js和TypeScript所禁用 SDK:为多租户SaaS和AI代理所嵌入的集成\. 您的客户通过一个打入的API将自己的应用程序连接到你的产品中\.

### 如何安装 @fastn-ai/sdk？

在项目目录运行 npm install @fastn-ai/sdk，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 fastn-sdk-tools，可以用 npx fastn-sdk-tools 直接运行。

### @fastn-ai/sdk 支持 TypeScript 吗？

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

### @fastn-ai/sdk 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @fastn-ai/sdk 需要什么版本的 Node\.js？

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

### @fastn-ai/sdk 可以商用吗？

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

### @fastn-ai/sdk 的下载量有多少？

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

### @fastn-ai/sdk 还在维护吗？

最新版本 0\.5\.1 发布于 2026/11/01（13 天前）；至今共发布 11 个版本，其中过去 12 个月发布了 11 个；首次发布于 2026/10/23。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

