# @crvouga/mockingbird-service-customerio 中文文档

规范地址：https://npmcn.com/package/%40crvouga/mockingbird-service-customerio/

版本：3\.11\.0
npm 元数据更新时间：2026-11-11T02:06:12.237Z
中文译文更新时间：2026-11-11T02:32:29.344Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40crvouga/mockingbird-service-customerio
原文对照：https://npmcn.com/package/%40crvouga/mockingbird-service-customerio/?lang=original
项目主页：https://github.com/crvouga/mockingbird/tree/main/packages/service/customerio#readme
源码仓库：https://github.com/crvouga/mockingbird

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

- 包体积（解压后）：4.5 MB，18 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：2 个
- 首次发布：2026-09-22T23:53:12.355Z
- 最新版本发布：2026-11-11T02:06:11.815Z
- 近 30 天下载量：16148（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：42（近 12 个月 42 个）

## 中文简介

Customer.io的状态仿真器:可兼容分块的 CDP(识别/跟踪/批发,SDK 滴入),App API 交易电子邮件/SMS/inbox 发送带有发箱,消息目录,点击链接跟踪,并签名报告webhooks.

## 安装

```sh
npm install @crvouga/mockingbird-service-customerio
```

也可以使用：`pnpm add @crvouga/mockingbird-service-customerio`、`yarn add @crvouga/mockingbird-service-customerio`、`bun add @crvouga/mockingbird-service-customerio`

## README

# @crvouga/ 嘲笑鸟 - 服务 - 客户

> 本地模拟器。 真正的API合同. 部分 [嘲笑鸟](https://github.com/crvouga/mockingbird)。 。 。 .

状态模拟器 **顾客.io** 测试套房,服务所有三个主机 我们的代码谈话从 一个进程: 与段相兼容 **发展政策委员会** (单位:千美元)`identify`, (中文(简体) ), `track`, (中文(简体) ), `batch`,与 `@customerio/cdp-analytics-node` 员额) **应用 API** 交易发送(电子邮件、短信、, 、收件箱信息、信息目录、配置属性读取、发送者选择退出调节、交付状态读取、以及 **链接跟踪** 点击结束点。 在一个发包箱中发送一个套件(并读取链接) (一) 报告活动(`unsubscribed`, (中文(简体) ), `subscribed`, (中文(简体) ), `spammed`,订阅偏好, `clicked`并签署客户签名的方式.

-   行动范围: [支助](https://github.com/crvouga/mockingbird/blob/main/packages/service/customerio/SUPPORT.md)
-   合同`openapi.yaml`)由Customer.io的CDP(分块谱)和App API手写 参考书目,与我们的消费者寄送的东西相对应.

## 安装

```bash
npm install -D @crvouga/mockingbird-service-customerio
```

仅限无害环境管理。 节点 22或 Bun 1.2. 无土生属地. 给它服务 `npx mockingbird-customerio serve`, (中文(简体) ), `createServer` 从 `./server` (节点),或 `createRuntime` 与任何获取服务器.

## 使用量

应用程序硬码为Customer.io的每个区域主机(`customer-io.config.ts`,接合G-Y1):一次 它们被env驱动,指向 CDP 主机(SDK's `host`, App API 主机和链接 跟踪模拟器中的域。 顾客.io只运行当 `CUSTOMERIO_RUNTIME_ENABLED` 开始和 舞台已经进入 `CUSTOMERIO_ALLOWED_STAGES`。 。 。 .

```bash
npx mockingbird-customerio serve --port 8810 \
  --webhook-url http://127.0.0.1:3000/v1/customer-io/reporting-webhook \
  --webhook-secret "$CUSTOMERIO_REPORTING_WEBHOOK_SIGNING_KEY"
```

```ts
import { Analytics } from "@customerio/cdp-analytics-node"
import { createServer } from "@crvouga/mockingbird-service-customerio/server"

const cio = await createServer({
  webhooks: { url: "http://127.0.0.1:3000/v1/customer-io/reporting-webhook", secret: "k".repeat(32) },
})

// The application's CDP client. Only its host changes.
const analytics = new Analytics({ writeKey: "wk", host: cio.url, maxEventsInBatch: 1 })
analytics.identify({ userId: "42", traits: { email: "ada@example.com" } })
await analytics.closeAndFlush()

// Test control. The member unsubscribes in Customer.io: the signed reporting event reaches the backend.
await fetch(`${cio.url}/__admin/reporting-events`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ metric: "unsubscribed", userId: "42", objectType: "customer" }),
})
await cio.close()
```

交易发送通过 App API 客户端(`customerio-node`),指出这一点 模拟器。 测试内容是:

```ts
import { Analytics } from "@customerio/cdp-analytics-node"
import { APIClient, SendEmailRequest } from "customerio-node"
import { createServer } from "@crvouga/mockingbird-service-customerio/server"

const cio = await createServer()

// The application's clients. Only the CDP host and the App API url change.
const analytics = new Analytics({ writeKey: "wk", host: cio.url, maxEventsInBatch: 1 })
const api = new APIClient("app-key", { url: `${cio.url}/v1` })
analytics.identify({ userId: "42", traits: { email: "ada@example.com" } })
await analytics.closeAndFlush()
await api.sendEmail(
  new SendEmailRequest({ transactional_message_id: 1, identifiers: { id: "42" }, to: "ada@example.com" }),
)

// Test assertions read the emulator's state.
const profiles = await (await fetch(`${cio.url}/__admin/profiles`)).json()
const deliveries = await (await fetch(`${cio.url}/__admin/outbox?userId=42`)).json()
await cio.close()
```

### 路线

| 路线 | 行为 |
| --- | --- |
| `POST /v1/identify`, (中文(简体) ), `/v1/track`, (中文(简体) ), `/v1/batch` | 发展政策委员会, `Authorization: Basic base64(<write key>:)` (原为401) `{error}`) (中文(简体) ). 部分活动(`batch` 联 合 国 `identify` 编号 : `track`(b) 每个需要 `userId` 或者说 `anonymousId` (减:400人) `{error}`,SDK不重试). 在适用任何条目之前,对批次进行验证。 → `{success: true}`查明浅层的特质; `cio_subscription_preferences.channels` 编号 : `.topics` 合并一个关卡, 因此省略密钥和清晰 `false` 留下来。 在一个剖面图上同时进行识别被序列化. 重复 `messageId` 被记录为复制而不适用. |
| `POST /v1/send/email`, (中文(简体) ), `/v1/send/sms`, (中文(简体) ), `/v1/send/inbox_message` | 应用API, `Authorization: Bearer <app key>` (原为401) `{meta: {error}}`) (中文(简体) ). `{transactional_message_id (id or trigger name, case-insensitive), identifiers: exactly one of id | email | cio_id, to?, from?, subject?, message_data?, send_to_unsubscribed?, tracked?, disable_message_retention?, headers?, attachments?}` → `{delivery_id, queued_at}`校验错误为 400 `{meta: {error}}`. 简讯 `to`,当存在时,必须是E.164. 与 `strictMessages`,一个未知的id是400 `{meta: {error: "transactional_message_id not found"}}`。一个 `identifiers.id` (a) 没有配置图可创建最小配置; `to` 保留字面上的收件人。 接受发送开始 `pending` (未交付). 未订阅的配置文件, 或其电子邮件/ SMS 频道 `false`获取 `suppressed` 除非 `send_to_unsubscribed` (框只跟随未订阅的旗帜). `disable_message_retention` 滴数 `message_data` 从发件箱中取出,除非 `retainMessageDataForTests`。 。 。 . `tracked: true` 重写每个 URL 为 `<trackingBase>/click/<linkId>`。没有发送能力:重复生成另一个发送. |
| `GET /v1/transactional` | `{messages: [{id, name, trigger_name, description, send_to_unsubscribed, link_tracking, …}]}`,不发作(整个目录,包括上百行). 种子与 `acme_<key>` 对于每个遗留的电子邮件密钥 消费者应用程序,还有 `acme_inbox_message` 财务报告和审定财务报表 `acme_playground_notification` (编号1-21). `transactionalListKey: "transactional"` 重命名数组密钥. |
| `GET /v1/transactional/{id}` | `{message: {...}}` 由 id 或触发名称(大小写不敏感),或 404 . |
| `GET /v1/customers/{customer_id}/attributes?id_type=id|email|cio_id` | `{customer: {identifiers: {id, email?, cio_id}, attributes, devices}}`未知号码 `id_type` 400; 不明客户为404。 属性传播存储的特性,然后 `id`, (中文(简体) ), `cio_id`, (中文(简体) ), `email`,以及 `unsubscribed` 赢了. |
| `GET /v1/optouts?limit=&start=&from=` | 工作空间发送器选择退出 `{optouts: [{customer_id, cio_id, optouts: [{channel, from}]}], next?}`。 。 。 . `limit` 默认为 100 (1-1000); 以下 `next` 使用 `start` 直到它缺席. `from` 过滤发件人/频道条目,省略没有匹配的人. 发件人值被修剪并小写;E.164数字保留其形式. |
| `GET /v1/customers/{customer_id}/optouts?id_type=id|email|cio_id` | `{optouts: [{channel, from}]}` 对于一个已有的配置文件,如果没有,则为空,对于未知的人则为404。 使用与 CDP 识别和配置更新相同的身份状态. App API 认证适用于两种读取. |
| `GET /v1/messages/{delivery_id}` | `{message: {id, type, recipient, customer_id, created, state, status, metrics}}`。 。 。 . `type` 实值 `in_app` 用于收件箱。 没有 `message_data`. 404 当id丢失或仍在里面 `statusVisibleAfterMs`。失败状态后添加 `failure_message`, (中文(简体) ), `rejection_reason`,以及 `error`。 。 。 . |
| `POST /click/{linkId}` | 我们的后端点击报告(未经认证) ^ 200,计算点击数并张贴a `clicked` 报告活动。 未知链接:平正文字 404. |
| `GET /click/{linkId}` | 浏览器沿着有轨链接 ~ 302 到原URL. |

### 汇报网点

`POST <webhook-url>` 与 `x-cio-timestamp: <unix seconds>` 财务报告和审定财务报表 `x-cio-signature: <hex HMAC-SHA256(secret, "v0:<timestamp>:<body>")>` (墙-钟时间戳. 车身 : `{event_id, object_type, metric, timestamp, data: {identifiers: {id, email, cio_id}, customer_id, email_address, delivery_id?, transactional_message_id?, href?, link_id?, content?}}`· ; `content` 是订阅首选项的 JSON 字符串. `timestamp` 永远不要赶在时分前跑 (我们的接收器拒绝事件 > 5分钟). 报复, `GET /__admin/webhooks`, (中文(简体) ), `…/events`, (中文(简体) ), `…/replay`, (中文(简体) ), `…/flush` 财务报告和审定财务报表 `PUT /__admin/webhook-endpoints` 工作如常.

### 管理员(超过标准合同)

| 路线 | 效果 |
| --- | --- |
| `GET /__admin/outbox?to=&recipient=&since=&channel=&transactional_message_id=&userId=&deliveryId=` | 交易性交货,最先交货`GET /__admin/outbox/:id` 一个: `channel`, (中文(简体) ), `to`, (中文(简体) ), `identifiers`, (中文(简体) ), `subject`, (中文(简体) ), `messageData`, (中文(简体) ), `links`, (中文(简体) ), `originalLinks`, (中文(简体) ), `tracked`, (中文(简体) ), `state` (单位:千美元)`pending` 直至过渡,或 `suppressed`, (中文(简体) ), `reason`, (中文(简体) ), `metrics`, (中文(简体) ), `clicks`, (中文(简体) ), `attachments` (档案名). `recipient` 匹配 `to`。日记记录方法、路径和状态,绝不是正文、API密钥或消息内容. |
| `POST /__admin/reporting-events` | `{metric, userId? | email? | deliveryId?, objectType?, preferences?: {topics?, channels?}}`: 将其应用到配置文件上 (`unsubscribed`, (中文(简体) ), `subscribed`, (中文(简体) ), `spammed`, (中文(简体) ), `cio_subscription_preferences_changed`)并张贴已签名的事件。 任何其他衡量标准(`delivered`, (中文(简体) ), `opened`, (中文(简体) ), `bounced`,.)作为-s发布. |
| `GET /__admin/cdp/events?userId=&type=&event=` | 收到的CDP电话(与 `duplicate`) (中文(简体) ). |
| `GET /__admin/profiles`, (中文(简体) ), `GET /__admin/profiles/:id`, (中文(简体) ), `PUT /__admin/profiles/:id` | 概况(海峡, `cioId`, (中文(简体) ), `unsubscribed`, (中文(简体) ), `channelsOff`, (中文(简体) ), `preferences`. PUT 合并 `{traits?, email?, unsubscribed?, preferences?}`。 。 。 . |
| `POST /__admin/optouts` | `{customerId, from, optout: boolean, channel?: "sms"|"whatsapp"}` 脚本停止( E)`true`)或裁武条约(`false`(b) 现有人员;身份不明者为404人。 只有发送/频道更改 。 营销偏好和报告网友保持独立. 国家参与命名空间、快照、时光线、钟表和重置. |
| `POST /__admin/deliveries/:id` | `{"state": "pending"|"sent"|"delivered"|"bounced"|"dropped"|"failed"|"spammed"|"undeliverable"|"suppressed"}`。邮票 `metrics[state]` 在命名空间时钟上有 unix 秒. `delivered` 失败状态是终极状态. |
| `POST /__admin/namespace-clock` | `{"advance": <ms>}` 仅添加此命名空间的时钟偏移 . |
| `GET|PUT /__admin/transactional` | 读取或替换工作空间的交易信件( E)`[{id?, name?, trigger_name, link_tracking?, send_to_unsubscribed?}]`) (中文(简体) ). |
| `GET|PUT /__admin/settings` | `{strictMessages?, trackingBase?, keys?, statusVisibleAfterMs?, clockOffsetMs?, retainMessageDataForTests?, transactionalListKey?}` (单位:千美元)`keys` 限制已接受的写入 / App API 密钥 . |

错误预设( E)`POST /__admin/faults {"preset": "<name>", "count"?: n}`· ; `GET /__admin/faults/presets`: `transactional_message_missing` (400元误差: `trigger_name_missing`然后退后,不交付, `transactional_404`, (中文(简体) ), `request_timeout_408` (408) 排队前,不交货,含糊不清, `server_error` (500后再排队,不交付,含糊不清), `accepted_but_500` (排好,然后500), `rate_limited` (429 有数字) `Retry-After`当然,没有交付, `invalid_app_key`, (中文(简体) ), `send_drop` 财务报告和审定财务报表 `send_drop_before_accept` (口袋在排队前关闭:模棱两可,不交货), `send_drop_after_accept` (交货记录,然后插座关闭:模棱两可,一次交货), `cdp_unavailable` (503; SDK 重试),, `cdp_bad_request` (400;没有重试), `cdp_slow` (15 s,过去) 10s的交货暂停, `transactional_list_unavailable`, (中文(简体) ), `omit_trigger_names` (单位:百万 `trigger_name`,或仅 `params.ids`, (中文(简体) ), `webhook_duplicate`, (中文(简体) ), `webhook_drop`, (中文(简体) ), `webhook_reorder`。 。 。 . 人工断层可以注射403或503或429个 `Retry-After` 是一个 HTTP 日期。 终止 (肯定失败)是被停止的仿真器,而不是预设. 401号 `{error}` 政策发展协调委员会 `{meta: {error}}` 在应用API。 映射到相同名称空间的密钥共享配置和交付; 两个命名空间不包含断层和时钟相冲。 重置一个命名空间 留下另一个.

### 命名空间

`x-mockingbird-namespace`页:1 `/__admin/ns/<name>` 在主机或按键上设置前缀: CDP 写入密钥( Basic 用户名)或 App API 密钥 (Bearer) 通过 `PUT /__admin/credentials {"credentials": {"<key>": "<namespace>"}}`。点击端点不带证书:使用页眉或前缀.

### 故意不模拟

-   Opt-out通过公共PUT API,电话标识工作空间配置,Twilio发件人身份外壳恢复,以及自动载体停止回调. 使用管理员控制来脚本调和器状态;它不模拟承运人的交付执行.
-   渲染: 未提供模板; 发件箱持有 `message_data`,而不是HTML. 翻译:.
-   运动、片段、出行、广播和轨道 API`track.customer.io`) (中文(简体) ).
-   发展政策委员会 `page`, (中文(简体) ), `screen`, (中文(简体) ), `group` 财务报告和审定财务报表 `alias` 电话(我们的消费者不发送).
-   附件仅用文件名记录 。 客户.io文件a `{filename: base64}` 地图; 我们的后端发送 `[{filename, content, content_type}]`二者均被接受;是否真实 API接受阵列形式未经验证(没有沙盒证书).
-   持发委东道机构`{success: true}`)和准确的 App API 错误字符串 `transactional_message_id not found` 未经证实.

## API 密码

| 导出 | 仁爱 | 说明 |
| --- | --- | --- |
| `CustomerIoAPI` | 类 | 进程模拟器 : `fetch(request)`, (中文(简体) ), `reset()`, (中文(简体) ), `report(input)`, (中文(简体) ), `profiles()`, (中文(简体) ), `mergeProfile(id, patch)`, (中文(简体) ), `transitionDelivery(id, state)`, (中文(简体) ), `advanceClock(ms)`, (中文(简体) ), `state`选项: `sqlite`, (中文(简体) ), `now`, (中文(简体) ), `wallClock`, (中文(简体) ), `namespace`, (中文(简体) ), `messages`, (中文(简体) ), `settings`, (中文(简体) ), `onReport`。 。 。 . |
| `createRuntime` | 函数 | 全面服务合同的仿真器(健康、管理、命名空间、证书、预设、发包、报告网络呼号)。 选项 : `webhooks: {url, secret, retryDelaysMs?, fetch?}`, (中文(简体) ), `messages`, (中文(简体) ), `settings`, (中文(简体) ), `clock`, (中文(简体) ), `wallClock`, (中文(简体) ), `seed`, (中文(简体) ), `adminKey`, (中文(简体) ), `onLog`, (中文(简体) ), `sqlite`。 。 。 . |
| `CUSTOMERIO_PRESETS` | 对象 | 每个命名的断层预设. |
| `CUSTOMERIO_NAMESPACE` | 字符串 | 服务名称, `"customerio"`。 。 。 . |
| `REPORTING_WEBHOOK_PATH` | 字符串 | 接收器的路径, `/v1/customer-io/reporting-webhook`。 。 。 . |
| `signReporting` | 函数 | `(secret, timestampSeconds, body)` - 六分卫 `x-cio-signature`。 。 。 . |
| `customerIoCredential` | 函数 | 请求所携带的写键或 App API 键 . |
| `DEFAULT_TRANSACTIONAL_MESSAGES`, (中文(简体) ), `DEFAULT_SETTINGS`, (中文(简体) ), `TRANSACTIONAL_EMAIL_KEYS` | 数值 | 种子目录,设置, 以及我们的后端遗留的电子邮件密钥. |
| `DELIVERY_STATES` | 数值 | 交付生命周期状态。 接受的发送起始于 `pending`。 。 。 . |
| `FAILURE_STATES` | 数值 | 终端失败状态 : `bounced`, (中文(简体) ), `dropped`, (中文(简体) ), `failed`, (中文(简体) ), `spammed`, (中文(简体) ), `undeliverable`, (中文(简体) ), `suppressed`。 。 。 . `delivered` 是成功的; `sent` 保持开放. |
| `document`, (中文(简体) ), `operationIds`, (中文(简体) ), `supportedOperationIds` | 数值 | 销售商为OpenAPI合同及其业务代号. |
| `createServer`, (中文(简体) ), `serveTarget`, (中文(简体) ), `DEFAULT_PORT` (单位:千美元)`./server`(中文(简体) ) | 节点 | 服务过来 `node:http`; 数据 `serve` CLI目标;出港8810. |

部分 [嘲笑鸟](https://github.com/crvouga/mockingbird)。 。 。 .

## 常见问题

### @crvouga/mockingbird-service-customerio 是什么？

Customer\.io的状态仿真器:可兼容分块的 CDP\(识别/跟踪/批发,SDK 滴入\),App API 交易电子邮件/SMS/inbox 发送带有发箱,消息目录,点击链接跟踪,并签名报告webhooks\.

### 如何安装 @crvouga/mockingbird-service-customerio？

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

### @crvouga/mockingbird-service-customerio 支持 TypeScript 吗？

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

### @crvouga/mockingbird-service-customerio 支持 ESM 还是 CommonJS？

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

### @crvouga/mockingbird-service-customerio 可以商用吗？

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

### @crvouga/mockingbird-service-customerio 的下载量有多少？

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

### @crvouga/mockingbird-service-customerio 还在维护吗？

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

