← 所有文章
更新日志

UnifyPort v1 API 正式生产可用:首个稳定版本里有什么 — UnifyPort

UnifyPort v1 API 现已正式生产可用。这是首个稳定版本:一个发送端点、一套归一化的 Webhook 事件层,以及覆盖全部六大渠道——WhatsApp、Telegram、LINE、TikTok、Zalo、X——的账号接入流程,全部收敛在同一个 API 之下。

这篇文章就是本次发布的更新日志。如果你一直在等一个可以放心构建、不必担心底层随时破坏性变更的版本,那就是它。下面按端点逐一说明本次上线的内容,包含真实的事件名、认证流程和可靠性行为。

一个发送 API,贯通六大渠道

v1 的核心是一个端点。POST /v1/messages 通过你选定的 provider 账号发送一条归一化的文本消息。你不需要学六套 SDK 或六种载荷格式——只学一套。

平台特有的能力并没有消失,而是收进了结构化的 provider_data 字段。需要回复某条特定消息,或设置 Telegram 的 parse mode?这些都放在 provider_data 里(例如 reply_toparse_mode),顶层请求的结构保持不变。常见场景保持简单,平台特定场景依然可行。

六大渠道为 WhatsApp、Telegram、LINE、TikTok、Zalo、X。在 API 里,provider 账号通过 telegramwhatsapptwitterlinezalo 等名称创建。

11 个标准 Webhook 事件

v1 的另一半是标准事件层。每一条来自 provider 的消息、每一次投递状态变更、每一个账号生命周期事件,都会被转换成同一套稳定的 JSON 结构。本次发布共有 11 个标准事件,你的后端通过同一个处理器消费它们全部。

最常用的两个:

  • message.received —— 已连接账号收到一条入站消息
  • message.status.updated —— 你发出的某条消息投递状态发生变化

账号生命周期事件让连接状态变得可观测,而不再是一团黑盒:

  • account.auth.required —— 账号需要一次登录操作(扫码或验证码)
  • account.auth.succeeded —— 登录完成;provider_account_ref 此时已填充,事件还携带标准资料字段(display_namepicture_urlregionstatus_message)
  • account.started —— 账号运行时已上线
  • account.status.updated —— 账号状态发生变化

无论来自六大渠道中的哪一个,message.received 事件长得都一样:

{
  "event": "message.received",
  "account_id": "acct_8Q2vK",
  "provider": "whatsapp",
  "from": "+6591234567",
  "text": "你好,我的订单好了吗?",
  "timestamp": 1749254400,
  "message_id": "wamid.HBgLNTU..."
}

whatsapp 换成 linezalo,你的路由逻辑一行都不用改。这正是标准层存在的意义。

账号接入:扫码与验证码两种流程

在 v1 里,账号接入是一条独立的流程,其设计理念是:认证状态是你的 Webhook 可以”观察”的东西,而不是需要你时刻盯着的东西。

你通过向账号端点 POST 创建账号,并选择与接入方式匹配的 auth_mode:

{
  "provider": "whatsapp",
  "auth_mode": "code",
  "provider_data": { "phone": "+6591234567" }
}

对于验证码流程,E.164 格式的手机号通过 provider_data.phone 提供。它会被持久化在账号上,并在后续认证动作中自动回放,因此你无需每一步都重新提交。创建重复的 provider 身份会返回干净的 409 duplicate_provider_account,而不是悄悄生成第二个账号。

对于扫码流程,凭据通过你的 Webhook 异步送达:

  • WhatsApp —— 调用 /auth/qr/start 开启设备会话。二维码 token 会作为 account.auth.required 事件落到你的 Webhook(auth_payload.qr_code 是你 UI 要渲染成二维码的原始 token),同时也通过 /auth/qr/check 提供同步轮询。扫码后,account.auth.succeeded 到达并带上 provider_account_ref,随后是 account.started
  • LINE —— 二维码 URL 与 PIN 异步送达。监听 account.auth.required,或轮询 /auth/session 读取 auth_payload.url(二维码图片)和 auth_payload.pin

账号配置好时,Webhook URL 会被自动注入——认证状态变更和登录事件,与你的入站消息走同一个端点。一个 Webhook,所有事件。

account.auth.succeeded 一旦到达,POST /v1/accounts/{account_id}/runtime/start 即可让账号上线(若运行时已启动则为空操作)。

Webhook 控制面

v1 里的 Webhook 端点是一等公民、可配置的对象,而不是埋在设置里的单个 URL 字段。

创建 Webhook 接收器时,你精确选择它接收哪些事件。subscribed_events 接受标准事件名(如 message.receivedaccount.status.updated),或用 ["*"] 订阅全部。未知的事件名在写入时即被拒绝,而不是稍后悄悄失败。

签名是内建的。提供 signing_secret,每次投递都会用 HMAC-SHA256 签名,你的端点即可验证真实性。留空则显式禁用签名——这是一个明确的选择,而非意外。

重试行为由你设定。retry_policy.max_attempts 是非负整数;0 表示完全禁用重试,非整数值会被拒绝。重投由平台负责,你的端点只需作出响应。

把波动留在平台层的可靠性

一个生产版本需要生产级默认值,v1 自带了它们。入站投递经过一条带限流、重试、幂等和故障隔离的队列,因此 provider 端的波动被留在平台层内部,不会级联到你的应用。

账号运行时状态也被归一化。runtime_status 不再是各家 provider 自己的术语,而是八个平台标准值之一——unknownstartingrunningstoppingstoppedreconnectingdisconnectederror——provider 特有的标签在你看到之前就已映射进这套取值。你只写一个状态机,而不是六个。

对于需要按地域路由的账号,可选的 proxy_config 对象会随账号持久化并自动应用。

这次发布意味着什么

v1 达到生产可用,是一种承诺,而不只是一个版本号。发送端点、11 个标准事件、认证流程、Webhook 控制面,就是你可以在其上构建产品的稳定面。UnifyPort 的初衷一直是:让团队不必把同一套集成做六遍;v1 就是这套面”停止移动”的那个版本。

如果你读过我们关于”绕开官方 API 摩擦接收消息”的其他文章——不走官方 API 接收 WhatsApp 入站无需官方账号接收 LINE 消息,或 WhatsApp 与 Telegram 成本对比——这就是那些路径所运行的 API。

上手步骤:创建一个 API key,用与渠道匹配的 auth_mode 连接第一个账号,注册一个带 signing_secret 的 Webhook 端点,订阅 message.received。同一个工作时段内,你就能看到归一化的入站事件打到后端。从此每多接一个渠道,都是同样的流程——而不是又一个集成项目。