Skip to content
AI 文档索引 ↗

事件接收协议 ​

本页供部署事件接收服务的团队核对请求、响应与重试规则。SDK 接入方只需配置 endpoint 和 projectKey;接收验证见数据校验。


协议要点 ​

  • SDK 创建事件时固定身份、Session 和时间戳;接收端不应以接收时的状态覆盖它们。
  • 未收到有效整批 ACK 时,SDK 可能重发同一批次。相同事件的 eventId 保持不变,普通重试的 batchId 也保持不变。
  • 接收端应按项目和事件 ID 处理重复请求。确认的范围始终是整批,不能按单条事件分别确认。

批量上报请求 ​

请求地址与请求头 ​

http
POST https://<collector-host>/v1/events/batch
Content-Type: application/json
X-Project-Key: <public-project-key>
X-Idempotency-Key: <batchId>
X-SDK-Name: <sdk-name>
X-SDK-Version: <sdk-version>
X-Protocol-Version: 1.0
Content-Encoding: gzip               # 压缩时使用

Web 页面离开时还可能发送 text/plain JSON 请求,不带上述自定义请求头。此时 projectKey、idempotencyKey、sdkName、sdkVersion 和 protocolVersion 在查询参数中;idempotencyKey 与正文 batchId 相同。这是尽力发送,不确认本地队列。接收端需单独验证该格式和重复事件处理。

projectKey 是公开项目凭据,不是认证密钥。接收端应自行执行访问控制;客户端请求中不应加入服务端 Secret。

请求体示例 ​

每个 Batch 包含不可变的批次信封与 events 事件列表,单条事件严格遵循 event-envelope.schema.json:

json
{
  "batchId": "batch_01JABC1234567890",
  "protocolVersion": "1.0",
  "sentAt": 1756100000500,
  "events": [
    {
      "schemaVersion": "1.0",
      "eventId": "evt_01JABC1234567890",
      "eventName": "order_checkout",
      "timestamp": 1756100000000,
      "sequence": 42,
      "sdk": {
        "name": "track-business-android",
        "version": "1.0.0"
      },
      "platform": "android",
      "identity": {
        "anonymousId": "anon_8f901c2",
        "sessionId": "sess_1a2b3c4",
        "userId": "user_9527",
        "identityEpoch": 1,
        "identityVersion": 3,
        "stateVersion": 7
      },
      "consent": {
        "level": "STANDARD",
        "timestamp": 1756100000000
      },
      "context": {
        "device": {
          "manufacturer": "Google",
          "model": "Pixel 8",
          "osVersion": "14"
        },
        "app": {
          "id": "com.example.app",
          "version": "2.1.0"
        }
      },
      "properties": {
        "orderId": "ord_9981",
        "amount": 199.0
      },
      "source": "manual",
      "capture": {
        "mode": "manual"
      },
      "trackingPlanVersion": "1.0"
    }
  ]
}

主要字段 ​

字段类型长度 / 范围说明
batchIdString8 ~ 128 字符本批次全局唯一标识符,重试保持不变
protocolVersionString固定 "1.0"契约协议版本号
sentAtIntegerUnix 毫秒时间戳发送端创建批次的时间;可结合接收时间辅助分析,网络延迟会影响偏差判断
eventsArray1 ~ 100 条事件数组,单条大小建议不超过 32 KB
events[].eventIdString8 ~ 128 字符单条事件幂等键;由 SDK 创建或按 API 提供,重试严禁变更,不限定 UUID 格式
events[].eventNameString1 ~ 128 字符事件名称;命名治理由事件目录或适用的 Tracking Plan 规定
events[].timestampIntegerUnix 毫秒时间戳事件创建时的 Unix 毫秒时间戳
events[].platformString枚举客户端事件为 web / android / ios;服务端事件为 server
events[].sourceString枚举采集方式:manual(应用/API 调用)或 auto(SDK/插件采集);无法判断时可省略

此页请求示例和 event-envelope.schema.json 描述客户端事件。Node.js、Java、Go、Python 服务端 SDK 使用独立的 server-event-profile.schema.json:其 platform 固定为 server,SDK 语言位于 sdk.language。两种 profile 共用批次传输和整批 ACK 语义;客户端 Schema 的 platform 枚举仍只包含客户端平台。


整批确认 ​

SDK 只有同时收到 HTTP 2xx 和有效响应体,才会确认队列。目标环境应返回以下包装响应:

json
{
  "code": 200,
  "data": { "status": "ACCEPTED" },
  "message": "success"
}

SDK 也接受平铺响应:响应体需包含与请求匹配的 batchId 和 accepted: "all"。

结果客户端处理
有效包装响应或匹配的平铺整批 ACK确认本批全部事件。旧逐事件字段和其他扩展元数据不参与 ACK 判定
2xx 只有旧 ACK 字段,缺少 accepted: "all"不构成有效 ACK;保留整批并按可重试协议错误处理
空体、无效 JSON 或无法识别的 2xx保留整批,按可重试协议错误处理
408、429、5xx、网络失败保留整批并重试
不可重试的 4xx整批死信
413多事件批次对半拆分;单条仍超限则本地拒绝

包装响应只依据 code=200 与 data.status="ACCEPTED" 确认当前请求批次。message 等附加字段不改变确认结果;成功响应体上限为 1 MiB。详情见可靠投递。


幂等与去重 ​

接收端需验证以下行为:

  1. 批次幂等键 (projectKey + batchId):
    • 相同项目收到相同 batchId 的请求时,接收端应根据已记录结果处理重试,避免重复处理;
    • 若相同 batchId 附带不同的请求内容,接收端应返回 409 和 BATCH_IDEMPOTENCY_CONFLICT。
  2. 事件幂等键 (projectKey + eventId):
    • 若客户端因拆批重发,将已在历史批次成功的 eventId 重新提交,接收端应按事件身份设计去重,避免重复统计;
    • 接收端应结合重试周期确定幂等记录的存储与保留期限;具体实现和可保证的范围由部署方确认。

错误响应与重试 ​

网关在处理连接层异常或全局错误时,返回标准的结构化 JSON 错误模型:

json
{
  "code": "RATE_LIMITED",
  "category": "rate_limit",
  "retryable": true,
  "requestId": "req_01JABC123",
  "message": "Tenant rate limit exceeded"
}

408、429 和 5xx 会保留整批并退避重试;429 可用 Retry-After 指定等待时间。413 会拆分多事件批次,拆分后每个子批使用新 batchId,原事件 eventId 不变。其他不可重试的 4xx 将整批移入死信。HTTP 2xx 仍必须满足上述 ACK 规则。


画像与实体操作 ​

机器可校验的请求结构源自 profile-operations.schema.json。SDK 将画像与 Item 操作编码为 $profile_* / $item_* 事件,并与普通事件共用 Store、批次上传、整批 ACK 和重试路径。若部署端实现这些操作的投影,应按其后端操作合同保证相应更新语义;SDK 收到整批 ACK 只表示 Collector 接受该批,不证明画像或 Item 投影已完成。

事件标识操作意图部署端实现责任
$profile_set覆盖更新指定属性后写覆盖已有同名属性,未提及属性完整保留
$profile_set_once首次初始化赋值仅在属性尚不存在时写入;已有属性严格保持不变
$profile_increment数值字段累加部署端按原子累加语义更新;存储实现由部署端决定,非数值输入按操作合同拒绝
$profile_append数组属性追加每个值为最多 100 项的同类型字符串或数值数组;请求 Schema 不规定接收端的去重策略
$profile_unset删除指定属性键属性移除,调用保持幂等
$profile_delete删除画像属性记录仅在部署端支持该操作时生效;不代表历史事件、备份或身份图谱的法定擦除流程
$item_set / $item_deleteItem 属性操作操作以 itemType 与 itemId 标识对象;存储隔离和生命周期由部署端定义

接收端验收 ​

部署接收服务前,建议核对:

  • [ ] 项目路由与隔离:按目标环境接收 X-Project-Key 及适用的 ?projectKey= 传参,验证项目路由、访问控制与租户数据隔离;公开 projectKey 本身不是服务端认证凭据;
  • [ ] Schema 强校验:请求体合法性基于 event-envelope.schema.json 强校验,非法属性被安全过滤或警告;
  • [ ] 整批确认:成功时返回 code: 200 与 data.status: "ACCEPTED";若使用兼容的平铺成功体,须包含匹配的 batchId 和 accepted: "all"。旧 acceptedEventIds / rejected / unresolved 不能单独确认。对无效、重复或受限事件的处理和诊断需在目标环境确认;
  • [ ] 幂等去重:确认接收端按 batchId 和 eventId 实现所需的去重语义及保留期限,并在 ACK 丢失后的重试场景验证;
  • [ ] 限流防护:在触发 429 限流时,返回合法的 Retry-After 秒级响应头;
  • [ ] 安全审计脱敏:网关链路日志中绝不打印用户密码、Token、未脱敏手机号或完整事件业务正文。