# Journey 对象

[生命周期](/zh/developer/api-reference/customer-journey-api/lifecycle/)、[创建和更新](/zh/developer/api-reference/customer-journey-api/create-update/) 方法都会返回一个具有相同顶级结构的 Journey 对象：

```json title="结构"
{
  "info": { ... },        // 只读元数据（仅在响应中）
  "params": { ... },      // Journey 范围的配置（创建/更新）
  "points": [ ... ],      // 画布节点及其连接
  "comments": [ ... ]     // 画布评论
}
```

当您 **创建** 或 **更新** 一个 Journey 时，您需要发送 `title`、`params`、`points` 和 `comments`。响应会返回 `info`（其中包含 `params`）以及 `points` 和 `comments`。

## Info

只读的 Journey 元数据。由每个 v3 方法返回。不属于请求正文的一部分。

| 字段 | 类型 | 描述 |
|---|---|---|
| `uuid` | string | [Journey ID](/zh/developer/api-reference/api-identifiers/#journey-id)。 |
| `title` | string | Journey 名称。 |
| `status` | [`JourneyStatus`](#journeystatus-enum) | 当前状态。 |
| `created_at` | string | 创建时间戳 (ISO 8601)。 |
| `updated_at` | string | 最后更新时间戳 (ISO 8601)。 |
| `is_first_activated` | bool | Journey 是否至少启动过一次。 |
| `params` | [`JourneyParams`](#journeyparams) | Journey 范围的配置。 |
| `category_uuid` | string | 类别的 UUID，如果未分类则为空。 |
| `pointCounts` | map&lt;string, uint32&gt; | 按类型统计的 point 数量。 |
| `campaign_type` | [`CampaignType`](#campaigntype-enum) | 用户进入 Journey 的方式。 |
| `stop_reason` | string | Journey 停止的原因（如果适用）。 |
| `last_edited_by` | `User` | 最后编辑此 Journey 的用户。 |
| `dynamic_entry` | bool | 是否启用了动态进入。 |

## JourneyParams

Journey 范围的配置。在创建/更新时发送，并在 `info.params` 内返回。

| 字段 | 类型 | 描述 |
|---|---|---|
| `application_code` | string | Journey 所属的 [Application code](/zh/developer/api-reference/api-identifiers/#application-code)。创建时必需。 |
| `silent_hours` | [`SilentHours`](#silenthours) | 每个渠道的消息静默时段。 |
| `capping` | [`EntryCapping`](#entrycapping) | 对用户可以重新进入 Journey 的频率限制。 |
| `conversion_window` | [`ConversionWindow`](#conversionwindow) | 用于归因目标转化的时间窗口。 |
| `user_id_track_change_policy` | [`UserIDTrackChangePolicy`](#useridtrackchangepolicy-enum) | 如何处理用户在 Journey 中途 ID 发生变化的情况。 |

### SilentHours

在静默时段内抑制发送。**按渠道** 配置：每个渠道都有自己的 `SilentHoursParams`：

| 字段 | 类型 | 描述 |
|---|---|---|
| `push_params` | `SilentHoursParams` | 推送通知的静默时段。 |
| `inapp_params` | `SilentHoursParams` | 应用内消息的静默时段。 |
| `email_params` | `SilentHoursParams` | 电子邮件的静默时段。 |
| `sms_params` | `SilentHoursParams` | 短信的静默时段。 |
| `whatsapp_params` | `SilentHoursParams` | WhatsApp 的静默时段。 |
| `line_params` | `SilentHoursParams` | LINE 的静默时段。 |

每个 `SilentHoursParams` 的结构如下：

| 字段 | 类型 | 描述 |
|---|---|---|
| `enabled` | bool | 静默时段是否适用于此渠道。 |
| `from_time` | `Time` | 静默窗口的开始时间：`{ "hour": 0–23, "minute": 0–59 }`。 |
| `to_time` | `Time` | 静默窗口的结束时间。 |
| `week_days` | bool[] | 七个布尔值，表示窗口适用的星期（星期一 = 索引 0）。 |
| `behavior` | enum | 当消息落入静默时段时应采取的措施：`WaitAndSend`（暂存，窗口结束后发送）、`DropAndGo`（跳过消息，立即继续 Journey）或 `WaitAndDrop`（等待窗口结束，然后不发送消息继续 Journey）。 |

### EntryCapping

限制同一用户进入 Journey 的频率。

| 字段 | 类型 | 描述 |
|---|---|---|
| `is_enabled` | bool | 是否启用进入限制。 |
| `period` | uint64 | 用户两次进入之间的最小秒数。 |

### ConversionWindow

| 字段 | 类型 | 描述 |
|---|---|---|
| `seconds` | uint64 | 用户进入 Journey 后，其目标完成仍被计为转化的时间长度。 |

## Point

Point 是 Journey 画布上的一个节点：入口点、消息、延迟、分割器等。

| 字段 | 类型 | 描述 |
|---|---|---|
| `uuid` | string | Point 在 Journey 内的唯一 ID。必须是规范的 [RFC 4122](https://www.rfc-editor.org/rfc/rfc4122) UUID：32 个十六进制数字，分为 8-4-4-4-12 组。 |
| `title` | string | Point 的显示名称。 |
| `point_type` | [`PointType`](#pointtype-enum) | 节点的种类。 |
| `outputs` | array of [`PointOutput`](#pointoutput) | 到下游 Point 的连接。 |
| `position` | [`Position`](#position) | 画布坐标。 |
| `point_data` | object | 只有一个嵌套键，与 `point_type` 匹配（参见 [point 类型](#point-types-and-point_data) 表）。 |

<Aside type="note">
所有 UUID（`info.uuid`、每个 point 的 `uuid` 以及每个 output 的 `next_point_uuid`）都必须是规范的 RFC 4122 UUID（8-4-4-4-12 十六进制组）。
</Aside>

### PointOutput

一个 Point 的 output 是其传出的分支。它们的键 **不是自由格式的**。验证器期望每种 Point 类型都有一组确切的键，并会拒绝那些 Point 具有错误数量的 output 或无法识别的键的 Journey。

| 字段 | 类型 | 描述 |
|---|---|---|
| `identity.key` | string | 分支键。必须遵循下面的 [output 键规则](#output-keys)。 |
| `identity.order` | int | 分支的显示顺序。 |
| `info.title` | string | 可选的分支标签。 |
| `info.next_point_uuid` | string | 此分支连接到的下一个 Point 的 UUID。 |

#### Output 键

默认（第一个）分支总是命名为 `"default"`。其他分支命名为 `"output1"`、`"output2"`……（前缀 `output` 后跟一个从 1 开始的索引）。有两种 Point 类型打破了此规则，如下所述。

| Point 类型 | 预期的 output 键 |
|---|---|
| 入口点 (`START_BY_SEGMENT`, `START_BY_API`, `EVENT`)、`INAPP`、`SET_TAGS`、`WEBHOOK`、`AUDIENCE_SYNC` 以及没有分割器的消息点 (`SEND_PUSH`, `SEND_EMAIL`, `SEND_SMS`, `SEND_WHATSAPP`, `SEND_LINE`, `SEND_KAKAO`, `SEND_TELEGRAM`, `SEND_DATA`) | `default` |
| `GOAL_EVENT`, `EXIT` | 无（没有 output） |
| `FILTER` | `default`, `output1` |
| `BOOLEAN_SPLITTER` | `default`，然后是 `output1` … `outputN`（每个条件一个额外分支。一个简单的“是/否”分割是 `default` + `output1`） |
| `WAIT` (delay) | `default`。带有分支分割的动态延迟会添加 `output1` |
| `WAIT_EVENT` | `default` 是 **事件未触发** 分支。`output1`（或者，如果有条件脚本，则每个条件一个分支）是触发路径 |
| `SEND_PUSH` 带有分割器 | `default`, `output1`（当消息和交付分割器都开启时，还有 `output2`） |
| `SEND_EMAIL` / `SEND_SMS` / `SEND_LINE` / `SEND_WHATSAPP` 带有分割器 | `default`, `output1` |
| `SEND_WHATSAPP` 带有快速回复预设 | `default`，外加每个快速回复一个分支。键是快速回复值本身 |
| `AB_SPLITTER` | `output0`, `output1`, `output2`, …（每个变体一个。**没有 `default` 分支**） |

### Position

| 字段 | 类型 | 描述 |
|---|---|---|
| `x` | float | 画布上的水平坐标。 |
| `y` | float | 画布上的垂直坐标。 |

## Point 类型和 point_data

`point_data` 是一个 one-of 结构：它只包含一个嵌套对象，其键由 Point 的 `point_type` 决定。

| `point_type` | `point_data` 键 | 用途 |
|---|---|---|
| `POINT_TYPE_START_BY_SEGMENT` | `start_by_segment` | 入口：匹配某个 Segment 的用户。 |
| `POINT_TYPE_EVENT` | `message_bus` | 入口：触发某个 Event 的用户。 |
| `POINT_TYPE_START_BY_API` | `start_by_api` | 入口：通过 [Start by API](/zh/developer/api-reference/customer-journey-api/start-by-api/) 调用注入的用户。 |
| `POINT_TYPE_WAIT` | `delay` | 等待一个固定或动态的时间间隔。 |
| `POINT_TYPE_WAIT_EVENT` | `wait_event` | 等待直到某个 Event 发生。 |
| `POINT_TYPE_SEND_PUSH` | `send_push` | 发送推送通知。 |
| `POINT_TYPE_SEND_EMAIL` | `send_email` | 发送电子邮件。 |
| `POINT_TYPE_SEND_SMS` | `send_sms` | 发送短信。 |
| `POINT_TYPE_SEND_WHATSAPP` | `send_whatsapp` | 发送 WhatsApp 消息。 |
| `POINT_TYPE_SEND_TELEGRAM` | `send_telegram` | 发送 Telegram 消息。 |
| `POINT_TYPE_SEND_KAKAO` | `send_kakao` | 发送 Kakao 消息。 |
| `POINT_TYPE_SEND_LINE` | `send_line` | 发送 LINE 消息。 |
| `POINT_TYPE_SEND_DATA` | `send_data` | 发送静默数据消息。 |
| `POINT_TYPE_INAPP` | `inapp` | 显示应用内消息。 |
| `POINT_TYPE_BOOLEAN_SPLITTER` | `boolean_splitter` | 按条件（Segment、Tag 或 Event）分割用户。 |
| `POINT_TYPE_AB_SPLITTER` | `ab_splitter` | 将用户分为 A/B 组。 |
| `POINT_TYPE_FILTER` | `filter` | 只允许匹配过滤器的用户继续。 |
| `POINT_TYPE_SET_TAGS` | `set_tags` | 更新用户 Tag。 |
| `POINT_TYPE_WEBHOOK` | `web_hook` | 发送一个出站 HTTP 请求。 |
| `POINT_TYPE_GOAL_EVENT` | `goal_event` | 跟踪一个转化目标。 |
| `POINT_TYPE_AUDIENCE_SYNC` | `audience_sync` | 将用户同步到外部受众。 |
| `POINT_TYPE_EXIT` | `terminator` | 退出 Journey。 |

<Aside type="note">
每种类型的 `point_data` 负载都在 [Point 参考](/zh/developer/api-reference/customer-journey-api/point-reference/) 中有详细文档。入口、计时、分割和操作点都在那里有完整介绍。消息点在信封级别进行介绍，并附有相关渠道文档的链接。
</Aside>

### Point 示例

一个带有单个下游连接的“设置 Tag” Point：

```json
{
  "uuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "title": "Tag as engaged",
  "point_type": "POINT_TYPE_SET_TAGS",
  "position": { "x": 480, "y": 120 },
  "outputs": [
    {
      "identity": { "key": "default", "order": 0 },
      "info": { "title": "", "next_point_uuid": "ffffffff-1111-2222-3333-444444444444" }
    }
  ],
  "point_data": {
    "set_tags": {
      "application_code": "XXXXX-XXXXX",
      "tags": [ { "name": "engaged", "value": "true" } ]
    }
  }
}
```

## JourneyComment

| 字段 | 类型 | 描述 |
|---|---|---|
| `id` | string | 评论 UUID。 |
| `message` | string | 评论文本。 |
| `position` | [`Position`](#position) | 画布坐标。 |
| `index` | int | 显示顺序。 |
| `created_at` | string | 创建时间戳 (ISO 8601)。 |
| `deleted` | bool | 评论是否已删除。 |

## 枚举

### JourneyStatus 枚举

`STATUS_DRAFT`、`STATUS_RUNNING`、`STATUS_FINISHED`、`STATUS_ARCHIVED`、`STATUS_PAUSED`、`STATUS_UNKNOWN`。

### CampaignType 枚举

- `TriggerBased`：用户因事件进入。
- `AudienceBased`：用户从 Segment 进入。
- `APIBased`：用户通过 Start by API 调用进入。
- `Mixed`：多种进入类型。
- `Unknown`：未确定进入类型。

### PointType 枚举

请参阅上面的 [point 类型](#point-types-and-point_data) 表，了解完整列表以及每种类型映射到的 `point_data` 键。

### UserIDTrackChangePolicy 枚举

控制当用户的 [User ID](/zh/developer/api-reference/api-identifiers/#user-id) 在 Journey 中途发生变化时会发生什么：

- `DEFAULT`：默认行为。
- `TRACK`：在新 ID 下继续跟踪用户。
- `DROP`：当用户 ID 改变时，将用户从 Journey 中移除。

## 相关

<CardGrid>
  <LinkCard title="Point 参考" href="/developer/api-reference/customer-journey-api/point-reference/" />
  <LinkCard title="创建和更新" href="/developer/api-reference/customer-journey-api/create-update/" />
  <LinkCard title="生命周期" href="/developer/api-reference/customer-journey-api/lifecycle/" />
</CardGrid>