跳到主要内容

开发者文档

第三方消息推送对接

说明当前服务端通知接口的认证、请求、幂等、限流、结果回调和安全约束。

快速开始

在 Web 管理后台为目标公司创建第三方应用,复制 App ID 和 App Secret;如需接收最终结果,再填写可选的 Callback URL。

Engine 会为可选 audience 选中的用户生成通知中心记录(默认是绑定公司的全部有效用户),并仅向符合条件的已注册设备尝试发送系统 Push。

接口与认证

API 环境:

第三方服务端发送的每个 JSON 请求都必须通过 HTTP Basic Authentication 携带 Authorization: Basic Base64(KEY:SECRET),其中 KEY 是 App ID,SECRET 是 App Secret:

接口:POST /openapi/v1/notifications。

bash
curl --request POST 'https://<your-engine-host>/openapi/v1/notifications' \
  --header 'Authorization: Basic <Base64(AppID:AppSecret)>' \
  --header 'Content-Type: application/json' \
  --data '{"requestId":"order-20260819-001","title":"订单已完成","body":"您的订单已经完成。","imageUrls":["https://cdn.example.com/order/001-1.webp","https://cdn.example.com/order/001-2.webp"],"displayFields":[{"label":"店铺名称","value":"小韩面(望京店)"},{"value":"ORD-10086"}],"tags":["已完成","望京店"]}'

请求契约

字段总览

字段必填类型含义
requestId是string调用方生成的请求唯一标识,也是幂等键;去除首尾空白后不能为空。
title是string通知标题;去除首尾空白后不能为空。
body是string通知正文;去除首尾空白后不能为空。
imageUrls否string[]通知详情中按顺序展示的图片 URL。
displayFields否object[]通知详情中按顺序展示的补充文本字段。
tags否string[]仅在通知详情中按顺序展示的纯文本标签。
audience否object将发送范围缩小到指定用户或公司角色;省略时发送给全公司有效用户。

图片 imageUrls

  • 省略、null 或 [] 都表示没有图片;否则可按展示顺序传入 1-9 个 URL。
  • 每个 URL 会去除首尾空白,必须唯一,并且是无用户名和密码的绝对 HTTPS URL。
  • 单个 URL 最多 2048 个 Unicode 字符;任一 URL 不合法都会拒绝整个请求。
  • Engine 只存储 URL,不会抓取、探测、代理或缓存图片。

展示字段 displayFields

子字段必填限制显示方式
label否去除首尾空白后不能为空;最多 32 Unicode 字符作为字段名称显示。
value是去除首尾空白后不能为空;最多 256 Unicode 字符作为字段内容显示。
json
{
  "displayFields": [
    { "label": "店铺名称", "value": "小韩面(望京店)" },
    { "value": "ORD-10086" }
  ]
}
  • 省略、null 或 [] 都表示没有额外字段;最多传 10 个对象。
  • 不含 label 或 label 为 null 的对象,会把 value 显示为独占整行。
  • 内容始终按 plain text 展示,不支持 HTML、Markdown、链接、嵌套数据、字段类型或样式指令。

详情标签 tags

  • 省略、传 null 或 [] 都表示没有标签;否则最多传 8 个字符串,并按传入顺序展示。
  • 每个标签会去除首尾空白,去除后必须为 1-20 Unicode 字符。空值、非字符串、超长值或去除空白后重复,都会让整个请求返回 INVALID_REQUEST。
  • 标签仅在通知详情中以不可点击的 plain text 展示,并保留原顺序。

发送对象 audience

type选择器ID 含义
USERSuserIds公司成员 ID
ROLESrolesCompanyRole ID;命中任一角色的有效成员都会接收。

公司成员 ID 可从 Web 管理后台的公司成员列表复制;该成员必须属于第三方应用绑定的公司。

json
{
  "audience": {
    "type": "USERS",
    "userIds": ["companyMemberId"]
  }
}
json
{
  "audience": {
    "type": "ROLES",
    "roles": ["roleId"]
  }
}
  • 省略 audience 或传 null 时,发送给绑定公司的全部有效用户。
  • 对应数组必须有 1-100 个原始字符串;ID 会被去除首尾空白,空白项被忽略,并按集合去重、排序。
  • 不存在、禁用、已删除或跨公司的 ID 会被忽略,其余有效对象照常接收。
  • 合法选择器没有命中有效对象时仍会受理,以 recipientCount=0 完成,绝不会回退为全公司发送。
  • 不匹配当前 type 的字段可省略或传 null;其他混用、未知 type、缺失或空数组、非字符串项、未知字段以及超过 100 项都会返回 INVALID_REQUEST。

限制与幂等

  • 完整请求体上限为 256 KiB;requestId、title、body 分别最多 128、100、1000 个 Unicode 字符。
  • 每个 App ID 每分钟最多 10 次、每小时最多 100 次。
  • 使用相同 requestId 和等价的规范化内容重试会返回原结果。图片、展示字段和 tags 均保留顺序;audience 按类型和目标 ID 集合比较,顺序和重复项不影响幂等性。
  • 相同 requestId 携带不同内容时返回 IDEMPOTENCY_CONFLICT。已完成请求的 status 可能是 SUCCESS、PARTIAL_SUCCESS 或 FAILED。

接收响应

合法请求返回 HTTP 202:

json
{
  "requestId": "order-20260819-001",
  "notificationId": "00000000-0000-0000-0000-000000000001",
  "status": "ACCEPTED"
}

ACCEPTED 仅表示 Engine 已保存请求并等待分发,不代表 APNs/FCM 或设备已经展示系统横幅。

Callback 结果

配置 Callback URL 后,Engine 会发送一次终态结果:

json
{
  "requestId": "order-20260819-001",
  "status": "PARTIAL_SUCCESS",
  "recipientCount": 8,
  "pushAcceptedCount": 1,
  "pushFailedCount": 1
}

recipientCount 是通知中心接收用户数;pushAcceptedCount 和 pushFailedCount 是 Push Outbox 批次数,不是用户数、设备数或系统横幅送达数。

Callback 测试

管理后台每次测试 Callback 时都会发送一个独立的探测事件:

json
{
  "requestId": "callback-test-<unique-id>",
  "status": "SUCCESS",
  "recipientCount": 1,
  "pushAcceptedCount": 1,
  "pushFailedCount": 0,
  "test": true
}

收到 test: true 时,只需校验结构并返回 2xx;不要将该探测事件关联到已提交的通知请求,也不要更新业务送达状态。其中的计数是固定探测值,不代表真实接收用户或 Push Outbox 批次。

终态 status 为 SUCCESS、PARTIAL_SUCCESS 或 FAILED。返回任意 2xx 即确认成功。

否则 Engine 会在 1 分钟、5 分钟、30 分钟、2 小时、6 小时和 24 小时后重试。当前 Callback 没有 HMAC 签名:必须使用 HTTPS、校验非测试结果的 requestId 是否属于己方请求、尽量限制入口暴露范围,并保证幂等处理。

错误说明

HTTPCode含义
400INVALID_REQUESTContent-Type、JSON 结构、大小或字段校验失败。
401INVALID_APP_CREDENTIALSApp ID 或 App Secret 无效。
403APPLICATION_INACTIVE应用或绑定公司未启用。
409IDEMPOTENCY_CONFLICT相同 requestId 被用于不同内容。
429RATE_LIMITED超过应用级限流。
503NOTIFICATION_UNAVAILABLE通知服务暂时不可用。

安全与发送范围

  • App ID 和 App Secret 是服务端到服务端凭证,禁止放入浏览器、移动 App、公开代码库、URL 或客户端存储;如有泄露请立即重置 App Secret。
  • 私有目标 ID 不会写入应用 logs,私有 audience 选择器和目标 ID 也不会进入 GraphQL、Push、Callback、realtime 或 navigation 载荷。
  • 不传 audience 时,绑定公司的全部有效用户都会获得通知中心记录;传入后只发送给解析出的有效对象,并计入 recipientCount。
  • 系统 Push 仅尝试发送到有效且允许 BUSINESS 分类的 PushInstallation,仍不保证每台设备一定显示系统横幅。
  • 完整的 imageUrls 列表只会出现在已授权的通知详情中,但 Engine 可能把 imageUrls 中的第一个 URL 发送给 APNs/FCM,用于原生系统横幅展示图片。displayFields 和 tags 不会进入 Push 或 Callback,且都是不可点击的 plain text;请勿放入密码、访问令牌、支付数据或其他敏感信息。
  • title 和 body 必须在没有图片时仍能完整表达通知;图片下载或渲染失败不会改变 accepted、Callback 或 Push 状态。
  • 移动客户端每张图片最多接受 5 MiB,且单张图片完整下载操作的超时时间为 10 秒。客户端不会跟随 3xx 重定向,因此每个 URL 都必须直接返回图片。
  • 移动客户端会直接从公共 CDN 下载图片,因此 URL 不得要求认证或 Cookie,且应至少保持 90 天可访问;CDN 会获得用户 IP、请求时间和 User-Agent。
  • URL 对应内容可能变化,如需稳定保留历史展示,请使用不可变对象 URL。