# REST API 接入指南

Arkme REST API 面向服务端、脚本和桌面程序。本文包含连接方式、字段合同、调用示例和全部接口参考。

## 开始调用

| 配置 | 值 |
| --- | --- |
| API 地址 | `https://openapi.jotmo.cc` |
| 请求格式 | `POST` + `application/json` |
| 认证 | `Authorization: Bearer arkme_...` |
| 机器合同 | [OpenAPI 3.1](v1/openapi.yaml) |

API Key 应保存在服务端 Secret 中。浏览器页面应通过开发者自己的 Backend 或 BFF 调用，不应把 API Key 写入前端代码。

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/profile/get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

所有成功响应使用同一结构：`code` 为 `200`，`data` 的字段由具体接口定义。调用失败时使用 HTTP 状态码和 `message` 判断原因；`request_id` 可用于问题排查。

```json
{
  "code": 200,
  "message": "请求成功",
  "request_id": "request-example-1",
  "data": {}
}
```

## 能力目录 {#rest-capabilities}

**账号**

- [`getCurrentUserProfile`](#getCurrentUserProfile) — `POST /api/v1/profile/get` — 获取当前用户资料
- [`getCurrentUserAccountBindings`](#getCurrentUserAccountBindings) — `POST /api/v1/account-bindings/get` — 获取账号绑定状态

**人物**

- [`resolvePeople`](#resolvePeople) — `POST /api/v1/people/resolve` — 解析人物

**聊天**

- [`listChatConversations`](#listChatConversations) — `POST /api/v1/chat/conversations/list` — 列出可读会话
- [`queryChatConversations`](#queryChatConversations) — `POST /api/v1/chat/conversations/query` — 查询聊天会话
- [`resolveChatConversations`](#resolveChatConversations) — `POST /api/v1/chat/conversations/resolve` — 解析可读会话
- [`listChatMembers`](#listChatMembers) — `POST /api/v1/chat/members/list` — 列出会话成员
- [`searchChatMessages`](#searchChatMessages) — `POST /api/v1/chat/messages/search` — 搜索聊天消息
- [`queryChatMessages`](#queryChatMessages) — `POST /api/v1/chat/messages/query` — 查询聊天消息
- [`batchGetChatMessages`](#batchGetChatMessages) — `POST /api/v1/chat/messages/batch-get` — 批量读取聊天消息
- [`readChatMessageContext`](#readChatMessageContext) — `POST /api/v1/chat/messages/context` — 读取消息上下文
- [`resolveChatTargets`](#resolveChatTargets) — `POST /api/v1/chat/targets/resolve` — 解析消息发送目标
- [`createPrivateChats`](#createPrivateChats) — `POST /api/v1/chat/conversations/create-private` — 创建真人私聊
- [`sendChatMessages`](#sendChatMessages) — `POST /api/v1/chat/messages/send` — 批量发送聊天消息
- [`queryGroupMessageModerationTargets`](#queryGroupMessageModerationTargets) — `POST /api/v1/chat/messages/moderation/query` — 查询群消息治理对象
- [`withdrawGroupMessages`](#withdrawGroupMessages) — `POST /api/v1/chat/messages/withdraw` — 批量撤回群消息
- [`batchGetGroupMembers`](#batchGetGroupMembers) — `POST /api/v1/chat/members/batch-get` — 批量读取群成员状态
- [`removeGroupMembers`](#removeGroupMembers) — `POST /api/v1/chat/members/remove` — 批量移出群成员
- [`setGroupJoinRestrictions`](#setGroupJoinRestrictions) — `POST /api/v1/chat/join-restrictions/set` — 批量设置入群限制
- [`listGroupJoinRestrictions`](#listGroupJoinRestrictions) — `POST /api/v1/chat/join-restrictions/list` — 列出群入群限制

**微信导入**

- [`queryWechatImportConversations`](#queryWechatImportConversations) — `POST /api/v1/wechat-import/conversations/query` — 查询微信导入会话
- [`resolveWechatImportConversations`](#resolveWechatImportConversations) — `POST /api/v1/wechat-import/conversations/resolve` — 解析微信导入会话
- [`batchGetWechatImportConversations`](#batchGetWechatImportConversations) — `POST /api/v1/wechat-import/conversations/batch-get` — 批量读取微信导入会话
- [`queryWechatImportMessages`](#queryWechatImportMessages) — `POST /api/v1/wechat-import/messages/query` — 查询微信导入消息
- [`batchGetWechatImportMessages`](#batchGetWechatImportMessages) — `POST /api/v1/wechat-import/messages/batch-get` — 批量读取微信导入消息
- [`listWechatImportGroupMembers`](#listWechatImportGroupMembers) — `POST /api/v1/wechat-import/group-members/list` — 列出微信导入群成员

**录音**

- [`queryRecordings`](#queryRecordings) — `POST /api/v1/recordings/query` — 查询录音
- [`resolveRecordingSpeakers`](#resolveRecordingSpeakers) — `POST /api/v1/recordings/speakers/resolve` — 解析录音说话人
- [`batchGetRecordings`](#batchGetRecordings) — `POST /api/v1/recordings/batch-get` — 批量读取录音
- [`queryRecordingTranscript`](#queryRecordingTranscript) — `POST /api/v1/recordings/transcript/query` — 查询录音转写
- [`queryRecordingSummaries`](#queryRecordingSummaries) — `POST /api/v1/recordings/summaries/query` — 查询录音总结与时间线
- [`readRecordingSummary`](#readRecordingSummary) — `POST /api/v1/recordings/summaries/read` — 读取录音总结与时间线

**通话**

- [`queryCalls`](#queryCalls) — `POST /api/v1/calls/query` — 查询通话
- [`batchGetCalls`](#batchGetCalls) — `POST /api/v1/calls/batch-get` — 批量读取通话
- [`queryCallTranscript`](#queryCallTranscript) — `POST /api/v1/calls/transcript/query` — 查询通话转写

**记录**

- [`listRecordContainers`](#listRecordContainers) — `POST /api/v1/record/containers/list` — 列出记录主题
- [`resolveRecordContainers`](#resolveRecordContainers) — `POST /api/v1/record/containers/resolve` — 解析记录主题
- [`queryRecordTimeline`](#queryRecordTimeline) — `POST /api/v1/record/timeline/query` — 查询记录时间线
- [`searchRecords`](#searchRecords) — `POST /api/v1/record/search` — 搜索记录
- [`batchGetRecords`](#batchGetRecords) — `POST /api/v1/record/records/batch-get` — 批量读取记录
- [`createRecords`](#createRecords) — `POST /api/v1/record/records/create` — 批量创建记录
- [`updateRecords`](#updateRecords) — `POST /api/v1/record/records/update` — 批量更新记录
- [`moveRecords`](#moveRecords) — `POST /api/v1/record/records/move` — 批量移动记录
- [`deleteRecords`](#deleteRecords) — `POST /api/v1/record/records/delete` — 批量删除记录

**安排**

- [`queryArrangements`](#queryArrangements) — `POST /api/v1/arrangement/query` — 查询安排
- [`batchGetArrangements`](#batchGetArrangements) — `POST /api/v1/arrangement/batch-get` — 批量读取安排
- [`createArrangements`](#createArrangements) — `POST /api/v1/arrangement/create` — 批量创建安排
- [`updateArrangements`](#updateArrangements) — `POST /api/v1/arrangement/update` — 批量更新安排
- [`transitionArrangements`](#transitionArrangements) — `POST /api/v1/arrangement/transition` — 批量流转安排状态
- [`deleteArrangements`](#deleteArrangements) — `POST /api/v1/arrangement/delete` — 批量删除安排

**团队**

- [`removeTeamMembers`](#removeTeamMembers) — `POST /api/v1/teams/members/remove` — 移除团队成员
- [`listMyTeams`](#listMyTeams) — `POST /api/v1/teams/list` — 列出我的团队
- [`resolveMyTeams`](#resolveMyTeams) — `POST /api/v1/teams/resolve` — 解析我的团队
- [`listTeamMembers`](#listTeamMembers) — `POST /api/v1/teams/members/list` — 列出团队成员
- [`createTeams`](#createTeams) — `POST /api/v1/teams/create` — 创建团队
- [`joinTeamsByPublicID`](#joinTeamsByPublicID) — `POST /api/v1/teams/join-by-jotmo-id` — 按即我号加入团队

**世界**

- [`queryWorldRecords`](#queryWorldRecords) — `POST /api/v1/world/records/query` — 查询世界动态
- [`batchGetWorldRecords`](#batchGetWorldRecords) — `POST /api/v1/world/records/batch-get` — 读取世界发布快照
- [`queryWorldReplies`](#queryWorldReplies) — `POST /api/v1/world/replies/query` — 查询世界评论
- [`publishWorldRecords`](#publishWorldRecords) — `POST /api/v1/world/records/publish` — 发布快记到世界
- [`unpublishWorldRecords`](#unpublishWorldRecords) — `POST /api/v1/world/records/unpublish` — 撤回世界发布
- [`queryWorldCandidates`](#queryWorldCandidates) — `POST /api/v1/world/candidates/query` — 查询已有世界候选
- [`getWorldInteractionSummary`](#getWorldInteractionSummary) — `POST /api/v1/world/interactions/summary` — 读取世界互动摘要
- [`markWorldInteractionsViewed`](#markWorldInteractionsViewed) — `POST /api/v1/world/interactions/mark-viewed` — 标记世界互动已查看

**机器人**

- [`queryBots`](#queryBots) — `POST /api/v1/bots/query` — 查询本人机器人
- [`batchGetBots`](#batchGetBots) — `POST /api/v1/bots/batch-get` — 读取机器人资料
- [`createBots`](#createBots) — `POST /api/v1/bots/create` — 创建机器人
- [`updateBotProfiles`](#updateBotProfiles) — `POST /api/v1/bots/profile/update` — 更新机器人资料
- [`deleteBots`](#deleteBots) — `POST /api/v1/bots/delete` — 删除机器人
- [`listGroupBotBindings`](#listGroupBotBindings) — `POST /api/v1/bots/group-bindings/list` — 列举机器人群绑定
- [`installGroupBots`](#installGroupBots) — `POST /api/v1/bots/group-bindings/install` — 安装群机器人
- [`removeGroupBots`](#removeGroupBots) — `POST /api/v1/bots/group-bindings/remove` — 移除群机器人
- [`setGroupBotContextPermissions`](#setGroupBotContextPermissions) — `POST /api/v1/bots/group-bindings/context-permissions/set` — 设置机器人群读取授权
- [`resolveBotConversations`](#resolveBotConversations) — `POST /api/v1/bots/conversations/resolve` — 定位机器人专属会话
- [`queryBotConversationMessages`](#queryBotConversationMessages) — `POST /api/v1/bots/conversations/messages/query` — 查询机器人会话历史
- [`queryBotRequestResult`](#queryBotRequestResult) — `POST /api/v1/bots/requests/result/query` — 查询机器人请求结果
- [`sendBotRequests`](#sendBotRequests) — `POST /api/v1/bots/requests/send` — 向机器人发送用户请求
- [`publishBotMessages`](#publishBotMessages) — `POST /api/v1/bots/messages/publish` — 以机器人身份发布消息
- [`getBotWebhookSecurity`](#getBotWebhookSecurity) — `POST /api/v1/bots/webhook-security/get` — 读取机器人 Webhook 安全设置
- [`setBotWebhookSecurity`](#setBotWebhookSecurity) — `POST /api/v1/bots/webhook-security/set` — 设置机器人 Webhook 安全规则

## 标识与组合规则 {#rest-identifiers}

| 标识 | 业务含义 | 可传入 |
| --- | --- | --- |
| `user_ref` | 当前调用账号范围内可跨业务复用的人物公开引用 | `participant_user_ref`、`participant_user_refs`、`target_user_ref`、`sender_user_refs` 等人物引用字段；参与人筛选不等于发送人筛选 |
| `chat_session_uid` | 即我私聊、群聊或联系人会话 | 聊天会话、消息和发送能力的同名字段，以及通话查询的 `chat_session_uids` |
| `chat_session_uid` + `sequence` | 当前会话中的消息 | 消息查询、搜索、精确读取与上下文能力的同名字段 |
| `conversation_uid` | 微信导入会话 | 微信导入消息、群成员读取的 `conversation_uid`，以及会话批量读取的 `conversation_uids` |
| `message_uid` | 微信导入消息 | 微信导入消息批量读取的 `message_uids`；不是即我聊天消息坐标 |
| `recording_uid` | 一条录音 | 录音批量读取的 `recording_uids`、转写查询的 `recording_uid` |
| `summary_uid` | 已保存的录音日总结或时间线版本 | 总结正文读取的 `summary_uid`；不能与 `recording_uid` 互换 |
| `speaker_uid` | 当前账号的正式录音说话人标记 | 录音查询的 `speaker_uids`；不是录音内的 `speaker_index`，不能用于其他业务 |
| `call_uid` | 一次通话 | 通话批量读取的 `call_uids`、转写查询的 `call_uid` |
| `topic_uid` | Record 个人主题 | 记录容器或安排能力的同名字段 |
| `record_uid` | 一条记录 | 记录读写能力或安排关联字段 |
| `arrangement_uid` | 一条安排 | 安排查询、更新、流转和删除能力 |
| `team_ref` | 当前账号范围内的团队引用 | 团队成员查询与移除的 team_ref 字段 |

不同标识不可互换。`topic_uid` 只表示个人主题；即我聊天使用 `chat_session_uid`，微信导入会话使用 `conversation_uid`。团队与群的成员关系独立；user_ref 可跨能力复用，成员权限由目标团队或群分别判断。持有标识不代表拥有读取权限。

`speaker_index` 和 `sender_index` 分别是本页 `speakers` 和 `senders` 的零基索引，不是人物标识，不可跨页或跨业务复用。只有返回了 `user_ref` 才可将该引用用于人物关联；不能仅按显示名合并身份，通话的 `participant_side` 也不代表参与人本人。微信导入群成员是导入快照中的当前名单，不是历史发言人集合或微信实时成员。

## 读取范围与完整性

录音查询的 order 缺省 asc，desc 从最新录音开始；最新指录音开始时间，不是上传或修改时间。时间条件按录音重叠范围筛选，有人物条件时要求该人物在范围内有有效话语。转写查询不继承列表筛选；省略时间窗时读取整条录音，显式传入 start_at/end_at 时，按重叠选择完整原句话语，不做字级时间裁剪。

已有稳定标识时可直接读取所需正文，无须先读取概览。录音和通话的批量读取返回概览或状态，转写正文由各自的转写查询分页返回。

已确认的即我账号使用 `user_ref`：录音对应 `speaker_user_refs`，通话对应 `participant_user_refs`，微信导入会话对应 `participant_user_ref`。录音与通话多目标取并集。微信无已绑定私聊时返回空，不代表没有相关微信数据；可按用户给出的微信名称解析候选，不推断账号绑定。录音标记名称使用说话人解析，微信备注名、昵称或群名使用微信导入会话解析；名称不自动合并身份。

解析与人物筛选均读取当前可见状态，不创建人物、会话或绑定。页间标记或绑定变化可能改变结果，需要一致重读时从第一页重新查询。空页仍应检查 `has_more`，扫描未结束不能断言不存在目标。

时间字段的单位、上下界是否包含、默认范围和排序以各能力字段合同为准，不跨业务套用。微信导入会话按最新消息时间筛选，消息按发送时间筛选；分析某段时间内的全部历史消息时，不要用同一时间窗预先排除会话，应不带时间条件枚举会话，再逐个查询目标时间范围内的消息。

需要覆盖整个查询范围时，按该能力的分页字段逐页读取，直到 `has_more=false`，不能按本页条数判断是否结束。使用不透明游标时，将返回的 `next_page_cursor` 原样传回 `page_cursor`，保持账号、能力、对象和筛选条件不变；`limit` 只控制单页大小，可以调整。每页处理后累计中间结果，需要引用时保留业务标识与原文定位信息。

分页结束只表示本次可读结果已读完，不保证业务数据完整。返回 `found=false` 表示当前不可读，不能推断对象不存在或已删除；转写还需判断 `transcript_state`，群成员还需判断 `roster_state`。媒体元数据也不等于可下载的媒体正文。

录音转写的 bounded 模式不通过继续分页补回截断句尾；需完整原话时改用 text_mode=full，从首页重新读取。full 模式按 utterance_index 和字符坐标拼接同一句的续片，不跨录音或结果快照复用话语序号；坐标以 Unicode code point 计数。truncated=true 表示当前项不是整句，不等于续读后仍缺正文。确认片段连续覆盖 text_total_length，并检查 transcript_state。通话转写及其他正文或名单仍按各自的截断合同处理，不能套用录音 full 模式或假定分页能补回截断内容。

录音总结是自动生成的参考内容；核对原话时读取转写，不必先读取或等待总结。已有 summary_uid 可直接读正文；需要选择版本时按覆盖时间查询。读取时先检查 found 和 content_state，仅 ready 返回正文，JSON 分片须拼齐后解析。查询和读取均不触发生成。

## 错误处理

| HTTP 状态 | 含义 | 调用方处理 |
| --- | --- | --- |
| `400` | 请求体、字段或枚举不符合接口合同 | 修正请求，不要原样重试 |
| `401` | API Key 缺失、无效或已删除，或账号不可用 | 检查 Key 和账号状态 |
| `429` | 请求过快或同时在途请求过多 | 遵循 `Retry-After`，使用带抖动的退避重试 |
| `502` | 对应业务能力暂时不可用 | 稍后重试；持续失败时提供 `request_id` |
| `503` | 开放平台暂时不可用 | 稍后重试；持续失败时提供 `request_id` |

写请求结果未知时，应使用完全相同的业务参数重试。接口包含 `idempotency_key` 时，同一业务意图必须复用原值，新的业务意图必须使用新值。批量结果按各接口的关联合同处理：包含 `item_id` 时逐项匹配；UID 数组精确读取按输入顺序与返回 UID 对应，并逐项检查可读状态。

字段表中的嵌套字段仅在其父对象存在时适用。

## 账号 {#rest-account}

### 获取当前用户资料 {#getCurrentUserProfile}

`POST /api/v1/profile/get`

返回当前 API Key 对应账号的昵称、即我号和创建时间，不返回登录凭据或联系方式。

Operation ID：`getCurrentUserProfile`

#### 请求字段

无字段，请求体使用 `{}`。

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/profile/get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `user_ref` | `string` | 是 | 当前 API Key 所属人物的公开引用，可直接用于接受 user_ref 的其他能力。 |
| `nickname` | `string` | 是 | 当前用户昵称。 |
| `jotmo_id` | `string` | 是 | 当前展示用即我号。 |
| `created_at` | `integer` | 是 | 账号创建时间，Unix 毫秒。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "created_at": 1700000000000,
    "jotmo_id": "xiaoming",
    "nickname": "小明",
    "user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 获取账号绑定状态 {#getCurrentUserAccountBindings}

`POST /api/v1/account-bindings/get`

返回当前账号六种登录方式的绑定状态，不返回手机号、邮箱或第三方账号标识。

Operation ID：`getCurrentUserAccountBindings`

#### 请求字段

无字段，请求体使用 `{}`。

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/account-bindings/get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 按平台固定顺序返回全部支持的登录方式绑定状态。 |
| `items[].provider` | `enum<string>` | 是 | 该绑定项对应的登录方式。 |
| `items[].bound` | `boolean` | 是 | 当前用户是否已绑定该登录方式。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].provider` | `phone` | 手机号登录方式。 |
| `items[].provider` | `email` | 邮箱登录方式。 |
| `items[].provider` | `wechat` | 微信登录方式。 |
| `items[].provider` | `apple` | Apple 登录方式。 |
| `items[].provider` | `google` | Google 登录方式。 |
| `items[].provider` | `huawei` | 华为登录方式。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bound": true,
        "provider": "phone"
      },
      {
        "bound": false,
        "provider": "email"
      },
      {
        "bound": true,
        "provider": "wechat"
      },
      {
        "bound": false,
        "provider": "apple"
      },
      {
        "bound": false,
        "provider": "google"
      },
      {
        "bound": false,
        "provider": "huawei"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 人物 {#rest-people}

### 解析人物 {#resolvePeople}

`POST /api/v1/people/resolve`

按昵称、联系人备注、即我号或“我/本人”分页查找当前账号具有真实业务关系的可见人物。

Operation ID：`resolvePeople`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量人物解析项，1 到 10 项；单项调用也传一个元素。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].query` | `string` | 是 | 人物昵称、联系人备注、即我号或“我/本人”，最多 100 字。 |
| `items[].limit` | `integer` | 否 | 本页候选上限，1 到 10；缺省为 5。 |
| `items[].page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/people/resolve' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"person-1","query":"小明","limit":5}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的人物解析结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].candidates` | `array<object>` | 是 | 当前账号业务可见的人物候选；选择后直接把 user_ref 传给下游能力。 |
| `items[].candidates[].user_ref` | `string` | 是 | 跨领域、REST 与 MCP 可复用的用户引用。 |
| `items[].candidates[].display_name` | `string` | 是 | 当前账号可见的人物显示名称。 |
| `items[].candidates[].jotmo_id` | `string` | 否 | 候选当前展示用即我号。 |
| `items[].candidates[].relationships` | `array<enum<string>>` | 是 | 当前账号与候选人物之间已由业务 Owner 证明的关系。 |
| `items[].has_more` | `boolean` | 是 | 是否还有下一页候选。 |
| `items[].next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].candidates[].relationships[]` | `self` | 候选就是当前 API Key 所属账号。 |
| `items[].candidates[].relationships[]` | `contact` | 候选是当前账号的有效联系人。 |
| `items[].candidates[].relationships[]` | `private_chat` | 候选是当前账号可见的私聊对象。 |
| `items[].candidates[].relationships[]` | `shared_group` | 候选与当前账号存在可见共享群聊。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "candidates": [
          {
            "display_name": "小明",
            "jotmo_id": "xiaoming",
            "relationships": [
              "contact",
              "private_chat"
            ],
            "user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
          }
        ],
        "has_more": false,
        "item_id": "person-1"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 聊天 {#rest-chat}

### 列出可读会话 {#listChatConversations}

`POST /api/v1/chat/conversations/list`

分页返回当前账号可读取的联系人、私聊和群聊会话，可按一个人物的参与关系筛选。该接口用于浏览会话，不保证每个结果都可作为消息发送目标。

Operation ID：`listChatConversations`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `scopes` | `array<enum<string>>` | 否 | 会话范围筛选；缺省包含全部可见范围。 |
| `participant_user_ref` | `string` | 否 | 可选参与人筛选；只返回该人物当前仍参与且当前账号可读的会话。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 100；缺省为 50。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `scopes[]` | `contact` | 可作为联系人目录结果使用。 |
| `scopes[]` | `private_chat` | 可作为私聊会话读取；pending 会话也可能属于此范围。 |
| `scopes[]` | `group_chat` | 可作为群聊会话读取或发送。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/conversations/list' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"scopes":["private_chat","group_chat"],"limit":50}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 按 chat_session_uid 升序稳定排列的本页可读会话。pending 结果可读取但不能直接作为发送目标。 |
| `items[].chat_session_uid` | `string` | 是 | 聊天会话 UID；只用于聊天查询、上下文和发送能力，不能作为 Record 个人主题 UID。 |
| `items[].kind` | `enum<string>` | 是 | 会话形态；pending 可读但不可直接发送。 |
| `items[].scopes` | `array<enum<string>>` | 是 | 该会话可用于的范围。 |
| `items[].display_name` | `string` | 否 | 当前账号可见的会话显示名称。 |
| `items[].participant_user_ref` | `string` | 否 | 真人 direct 会话的唯一对端用户引用；群聊、待注册私聊和机器人私聊不提供。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].kind` | `direct` | 已建立的私聊会话，可以作为消息发送目标。 |
| `items[].kind` | `pending` | 可读取的联系人会话，尚不能直接作为消息发送目标。 |
| `items[].kind` | `group` | 群聊会话，可以作为消息发送目标。 |
| `items[].scopes[]` | `contact` | 可作为联系人目录结果使用。 |
| `items[].scopes[]` | `private_chat` | 可作为私聊会话读取；pending 会话也可能属于此范围。 |
| `items[].scopes[]` | `group_chat` | 可作为群聊会话读取或发送。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "chat_session_uid": "chat-session-1",
        "display_name": "小明",
        "kind": "direct",
        "scopes": [
          "private_chat"
        ]
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询聊天会话 {#queryChatConversations}

`POST /api/v1/chat/conversations/query`

按会话当前最新可见消息时间范围查询联系人、私聊和群聊，可按一个人物的参与关系筛选；结果按最新消息时间稳定分页。

Operation ID：`queryChatConversations`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `scopes` | `array<enum<string>>` | 否 | 会话范围筛选；缺省包含全部可见范围。 |
| `participant_user_ref` | `string` | 否 | 可选参与人筛选；只返回该人物当前仍参与且当前账号可读的会话。 |
| `last_message_from` | `integer` | 是 | 只返回当前最新可见消息时间不早于此值的会话，Unix 毫秒。 |
| `last_message_before` | `integer` | 否 | 只返回当前最新可见消息时间早于此值的会话，Unix 毫秒；留空表示不设上界。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `scopes[]` | `contact` | 可作为联系人目录结果使用。 |
| `scopes[]` | `private_chat` | 可作为私聊会话读取；pending 会话也可能属于此范围。 |
| `scopes[]` | `group_chat` | 可作为群聊会话读取或发送。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/conversations/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"scopes":["private_chat","group_chat"],"last_message_from":1700000000000,"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 按 last_message_at 降序、chat_session_uid 升序稳定排列的会话。 |
| `items[].chat_session_uid` | `string` | 是 | 聊天会话 UID；只用于聊天查询、上下文和发送能力，不能作为 Record 个人主题 UID。 |
| `items[].kind` | `enum<string>` | 是 | 会话形态；pending 可读但不可直接发送。 |
| `items[].scopes` | `array<enum<string>>` | 是 | 该会话可用于的范围。 |
| `items[].display_name` | `string` | 否 | 当前账号可见的会话显示名称。 |
| `items[].participant_user_ref` | `string` | 否 | 真人 direct 会话的唯一对端用户引用；群聊、待注册私聊和机器人私聊不提供。 |
| `items[].last_message_at` | `integer` | 是 | 会话当前最新可见消息时间，Unix 毫秒。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].kind` | `direct` | 已建立的私聊会话，可以作为消息发送目标。 |
| `items[].kind` | `pending` | 可读取的联系人会话，尚不能直接作为消息发送目标。 |
| `items[].kind` | `group` | 群聊会话，可以作为消息发送目标。 |
| `items[].scopes[]` | `contact` | 可作为联系人目录结果使用。 |
| `items[].scopes[]` | `private_chat` | 可作为私聊会话读取；pending 会话也可能属于此范围。 |
| `items[].scopes[]` | `group_chat` | 可作为群聊会话读取或发送。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "chat_session_uid": "chat-session-1",
        "display_name": "小明",
        "kind": "direct",
        "last_message_at": 1700001000000,
        "scopes": [
          "private_chat"
        ]
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 解析可读会话 {#resolveChatConversations}

`POST /api/v1/chat/conversations/resolve`

按名称或自然语言批量查找可读取的联系人、私聊和群聊会话，并分页返回稳定候选。

Operation ID：`resolveChatConversations`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量会话解析项，1 到 10 项；单项调用也传一个元素。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].query` | `string` | 是 | 会话名称或可用于识别会话的自然语言，最多 100 字。 |
| `items[].scopes` | `array<enum<string>>` | 否 | 会话解析范围；缺省包含全部可见范围。 |
| `items[].limit` | `integer` | 否 | 本页候选上限，1 到 10；缺省为 5。 |
| `items[].page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].scopes[]` | `contact` | 可作为联系人目录结果使用。 |
| `items[].scopes[]` | `private_chat` | 可作为私聊会话读取；pending 会话也可能属于此范围。 |
| `items[].scopes[]` | `group_chat` | 可作为群聊会话读取或发送。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/conversations/resolve' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"conversation-1","query":"项目讨论群","scopes":["group_chat"],"limit":5}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的会话解析结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].candidates` | `array<object>` | 是 | 当前账号可读的会话候选；选择后直接把 chat_session_uid 传给下游能力。 |
| `items[].candidates[].chat_session_uid` | `string` | 是 | 聊天会话 UID；只用于聊天查询、上下文和发送能力，不能作为 Record 个人主题 UID。 |
| `items[].candidates[].kind` | `enum<string>` | 是 | 会话形态；pending 可读但不可直接发送。 |
| `items[].candidates[].scopes` | `array<enum<string>>` | 是 | 该会话可用于的范围。 |
| `items[].candidates[].display_name` | `string` | 是 | 当前账号可见的会话显示名称。 |
| `items[].candidates[].participant_user_ref` | `string` | 否 | 真人 direct 会话的唯一对端用户引用。 |
| `items[].has_more` | `boolean` | 是 | 是否还有下一页候选。 |
| `items[].next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].candidates[].kind` | `direct` | 已建立的私聊会话，可以作为消息发送目标。 |
| `items[].candidates[].kind` | `pending` | 可读取的联系人会话，尚不能直接作为消息发送目标。 |
| `items[].candidates[].kind` | `group` | 群聊会话，可以作为消息发送目标。 |
| `items[].candidates[].scopes[]` | `contact` | 可作为联系人目录结果使用。 |
| `items[].candidates[].scopes[]` | `private_chat` | 可作为私聊会话读取；pending 会话也可能属于此范围。 |
| `items[].candidates[].scopes[]` | `group_chat` | 可作为群聊会话读取或发送。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "candidates": [
          {
            "chat_session_uid": "chat-session-2",
            "display_name": "项目讨论群",
            "kind": "group",
            "scopes": [
              "group_chat"
            ]
          }
        ],
        "has_more": false,
        "item_id": "conversation-1"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 列出会话成员 {#listChatMembers}

`POST /api/v1/chat/members/list`

分页列出一个当前可读会话中的有效真人成员，返回可跨能力复用的用户引用。

Operation ID：`listChatMembers`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `chat_session_uid` | `string` | 是 | 已知且当前可读的聊天会话 UID。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 100；缺省为 50。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/members/list' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"chat_session_uid":"chat-session-1","limit":50}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 按成员稳定身份升序返回的当前有效真人成员。 |
| `items[].user_ref` | `string` | 是 | 可跨人物、聊天与记录能力复用的公开用户引用。 |
| `items[].display_name` | `string` | 否 | 当前账号在该会话内可见的成员名称。 |
| `items[].role` | `enum<string>` | 是 | 成员在当前会话中的角色。 |
| `items[].joined_at` | `integer` | 是 | 成员加入当前会话的业务时间，Unix 毫秒。 |
| `has_more` | `boolean` | 是 | 是否还有下一页成员。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].role` | `owner` | 当前会话的拥有者。 |
| `items[].role` | `admin` | 当前会话的管理员。 |
| `items[].role` | `participant` | 当前会话的普通参与者。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "display_name": "小明",
        "joined_at": 1699990000000,
        "role": "participant",
        "user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 搜索聊天消息 {#searchChatMessages}

`POST /api/v1/chat/messages/search`

在一个或多个已知可读会话中按关键词搜索消息，可按发送人和消息时间筛选。

Operation ID：`searchChatMessages`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `keyword` | `string` | 是 | 消息标题或正文中的关键词，1 到 100 字。 |
| `chat_session_uids` | `array<string>` | 是 | 要搜索的已知会话 UID，1 到 100 个。 |
| `sender_user_refs` | `array<string>` | 否 | 仅搜索这些真人发送者的消息，最多 100 人。 |
| `start_at` | `integer` | 否 | 可选消息起始时间（含），Unix 毫秒。 |
| `end_at` | `integer` | 否 | 可选消息结束时间（不含），Unix 毫秒；提供时必须晚于 start_at。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/messages/search' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"keyword":"同步进度","chat_session_uids":["chat-session-1"],"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 按搜索相关性及消息时间稳定返回的当前有效命中证据。 |
| `items[].chat_session_uid` | `string` | 是 | 命中消息所属的聊天会话 UID。 |
| `items[].sequence` | `integer` | 是 | 消息在所属会话中的稳定顺序号；与 chat_session_uid 共同用于精确读取或上下文查询。 |
| `items[].sender_kind` | `enum<string>` | 是 | 消息发送主体类别。 |
| `items[].sender_user_ref` | `string` | 否 | sender_kind 为 user 时的公开用户引用。 |
| `items[].sender_bot_uid` | `string` | 否 | sender_kind 为 bot 时的机器人 UID。 |
| `items[].sender_name` | `string` | 否 | 当前账号可见的发送者显示名称。 |
| `items[].message_at` | `integer` | 是 | 消息业务时间，Unix 毫秒。 |
| `items[].matched_fields` | `array<enum<string>>` | 是 | 关键词命中的消息字段。 |
| `items[].snippet` | `string` | 是 | 当前正文中关键词附近的有界摘要；需要完整正文时调用批量精确读取。 |
| `has_more` | `boolean` | 是 | 是否还有下一页候选。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].matched_fields[]` | `title` | 关键词命中消息标题。 |
| `items[].matched_fields[]` | `body` | 关键词命中消息正文。 |
| `items[].sender_kind` | `user` | 发送主体是真实用户；读取 sender_user_ref。 |
| `items[].sender_kind` | `bot` | 发送主体是机器人；读取 sender_bot_uid。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "chat_session_uid": "chat-session-1",
        "matched_fields": [
          "body"
        ],
        "message_at": 1700001000000,
        "sender_kind": "user",
        "sender_name": "小明",
        "sender_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
        "sequence": 42,
        "snippet": "周五下午三点同步进度"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询聊天消息 {#queryChatMessages}

`POST /api/v1/chat/messages/query`

在指定会话和时间范围内查询可见消息，可按发送人筛选并通过游标继续读取；结果按会话分组，消息通过 sender_index 引用组内去重的发送者事实。

Operation ID：`queryChatMessages`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `chat_session_uids` | `array<string>` | 是 | 要查询的会话 UID，1 到 100 个。 |
| `sender_user_refs` | `array<string>` | 否 | 仅返回这些发送人的消息，最多 100 人；引用来自人物解析或其他公开能力。 |
| `start_at` | `integer` | 是 | 查询起始时间（含），Unix 毫秒。 |
| `end_at` | `integer` | 是 | 查询结束时间（不含），Unix 毫秒；必须晚于 start_at，时间窗不超过 366 天。 |
| `order` | `enum<string>` | 是 | 跨会话消息的稳定排序方向。 |
| `limit` | `integer` | 否 | 跨会话合计返回上限，1 到 500；缺省为 100。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `order` | `session_time_asc` | 按 chat_session_uid 与消息业务时间升序读取，适合顺序分析对话。 |
| `order` | `session_time_desc` | 按 chat_session_uid 与消息业务时间降序读取，适合从各会话较新消息向前读取。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/messages/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"chat_session_uids":["chat-session-1"],"start_at":1700000000000,"end_at":1700086400000,"order":"session_time_asc","limit":100}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 按 order 指定的 chat_session_uid 顺序分组；各组 messages 保持消息业务时间的稳定顺序。 |
| `items[].chat_session_uid` | `string` | 是 | 本组消息所属的聊天会话 UID。 |
| `items[].senders` | `array<object>` | 是 | 本组去重后的发送者事实；messages.sender_index 引用此数组。 |
| `items[].senders[].sender_kind` | `enum<string>` | 是 | 消息发送主体类别。 |
| `items[].senders[].sender_user_ref` | `string` | 否 | sender_kind 为 user 时的公开用户引用。 |
| `items[].senders[].sender_bot_uid` | `string` | 否 | sender_kind 为 bot 时的机器人 UID。 |
| `items[].senders[].sender_name` | `string` | 否 | 当前账号可见的发送者显示名称快照；同一身份名称变化时会占用不同索引。 |
| `items[].messages` | `array<object>` | 是 | 当前会话内按请求顺序排列的消息证据。 |
| `items[].messages[].sequence` | `integer` | 是 | 消息在所属会话中的稳定顺序号；与 chat_session_uid 共同定位消息。 |
| `items[].messages[].sender_index` | `integer` | 是 | 当前会话组 senders 数组的零基索引。 |
| `items[].messages[].message_at` | `integer` | 是 | 消息业务时间，Unix 毫秒。 |
| `items[].messages[].record_state` | `enum<string>` | 是 | 消息正文可用性；仅 available 返回正文，unavailable 不等同于 missing。 |
| `items[].messages[].title` | `string` | 否 | 消息标题；内容不可见或不存在时省略。 |
| `items[].messages[].text_content` | `string` | 否 | 用于分析的有界纯文本；需要完整当前正文时使用批量精确读取。 |
| `items[].messages[].content_truncated` | `boolean` | 否 | 为 true 表示正文因公开接口长度限制被截断。 |
| `has_more` | `boolean` | 是 | 是否还有下一页消息。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].messages[].record_state` | `available` | 正文已读取，可以使用返回的标题和文本内容。 |
| `items[].messages[].record_state` | `missing` | 对应正文不存在或已不再作为可见正文提供。 |
| `items[].messages[].record_state` | `unavailable` | 本次无法取得正文，不代表正文不存在，可以稍后重新读取。 |
| `items[].messages[].record_state` | `protected` | 正文存在但受保护，不返回标题和文本内容。 |
| `items[].senders[].sender_kind` | `user` | 发送主体是真实用户；读取 sender_user_ref。 |
| `items[].senders[].sender_kind` | `bot` | 发送主体是机器人；读取 sender_bot_uid。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "chat_session_uid": "chat-session-1",
        "messages": [
          {
            "message_at": 1700001000000,
            "record_state": "available",
            "sender_index": 0,
            "sequence": 42,
            "text_content": "周五下午三点同步进度"
          }
        ],
        "senders": [
          {
            "sender_kind": "user",
            "sender_name": "小明",
            "sender_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
          }
        ]
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量读取聊天消息 {#batchGetChatMessages}

`POST /api/v1/chat/messages/batch-get`

按会话 UID 与会话内消息顺序号精确读取当前消息事实；适合在搜索或分析后取得完整当前文本。

Operation ID：`batchGetChatMessages`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 需要精确读取的会话消息坐标，1 到 10 项；坐标不得重复。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].chat_session_uid` | `string` | 是 | 消息所在的已知会话 UID。 |
| `items[].sequence` | `integer` | 是 | 消息在所属会话中的顺序号；通常来自消息查询或搜索结果。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/messages/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"message-1","chat_session_uid":"chat-session-1","sequence":42}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的精确读取结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].lookup_status` | `enum<string>` | 是 | 指定会话消息坐标的当前读取结果。 |
| `items[].message` | `null or object` | 否 | lookup_status 为 found 时返回完整当前文本；正文状态仍由 message.record_state 独立表达。 |
| `items[].message.chat_session_uid` | `string` | 是 | 消息所属的聊天会话 UID。 |
| `items[].message.sequence` | `integer` | 是 | 消息在所属会话中的稳定顺序号；与 chat_session_uid 共同定位消息。 |
| `items[].message.sender_kind` | `enum<string>` | 是 | 消息发送主体类别。 |
| `items[].message.sender_user_ref` | `string` | 否 | sender_kind 为 user 时的公开用户引用。 |
| `items[].message.sender_bot_uid` | `string` | 否 | sender_kind 为 bot 时的机器人 UID。 |
| `items[].message.sender_name` | `string` | 否 | 当前账号可见的发送者显示名称快照。 |
| `items[].message.message_at` | `integer` | 是 | 消息业务时间，Unix 毫秒。 |
| `items[].message.record_state` | `enum<string>` | 是 | 消息正文可用性；仅 available 返回正文。 |
| `items[].message.record_uid` | `string` | 否 | 当前账号可修改这条消息对应的原生记录时返回的记录 UID。 |
| `items[].message.record_version` | `integer` | 否 | 返回 record_uid 时对应的当前记录版本号。 |
| `items[].message.mutable` | `boolean` | 否 | 为 true 表示当前账号可用 record_uid 和 record_version 修改这条消息对应的记录。 |
| `items[].message.title` | `string` | 否 | 消息标题；内容不可见或不存在时省略。 |
| `items[].message.text_content` | `string` | 否 | 消息纯文本内容；内容不可见或不存在时省略。 |
| `items[].message.content_truncated` | `boolean` | 否 | 为 true 表示正文因公开接口长度限制被截断。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].lookup_status` | `found` | 指定的会话消息当前可读；读取 message。 |
| `items[].lookup_status` | `not_found` | 指定的会话消息坐标不存在或当前不可读；不返回 message。 |
| `items[].message.record_state` | `available` | 正文已读取，可以使用返回的标题和文本内容。 |
| `items[].message.record_state` | `missing` | 对应正文不存在或已不再作为可见正文提供。 |
| `items[].message.record_state` | `unavailable` | 本次无法取得正文，不代表正文不存在，可以稍后重新读取。 |
| `items[].message.record_state` | `protected` | 正文存在但受保护，不返回标题和文本内容。 |
| `items[].message.sender_kind` | `user` | 发送主体是真实用户；读取 sender_user_ref。 |
| `items[].message.sender_kind` | `bot` | 发送主体是机器人；读取 sender_bot_uid。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "item_id": "message-1",
        "lookup_status": "found",
        "message": {
          "chat_session_uid": "chat-session-1",
          "message_at": 1700001000000,
          "mutable": true,
          "record_state": "available",
          "record_uid": "record-1",
          "record_version": 1,
          "sender_kind": "user",
          "sender_name": "小明",
          "sender_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
          "sequence": 42,
          "text_content": "周五下午三点同步进度"
        }
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 读取消息上下文 {#readChatMessageContext}

`POST /api/v1/chat/messages/context`

围绕同一会话内的指定消息顺序号读取有界上下文；消息通过 sender_index 引用去重的发送者事实。

Operation ID：`readChatMessageContext`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `chat_session_uid` | `string` | 是 | 消息所在的会话 UID。 |
| `sequences` | `array<integer>` | 是 | 需要读取上下文的会话内消息顺序号，1 到 80 个正整数且不得重复。 |
| `snapshot_at` | `integer` | 否 | 可选快照时间，Unix 毫秒；留空读取当前可见版本。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/messages/context' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"chat_session_uid":"chat-session-1","sequences":[42]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `chat_session_uid` | `string` | 是 | 本次上下文所属的聊天会话 UID。 |
| `senders` | `array<object>` | 是 | 上下文中去重后的发送者事实；messages.sender_index 引用此数组。 |
| `senders[].sender_kind` | `enum<string>` | 是 | 消息发送主体类别。 |
| `senders[].sender_user_ref` | `string` | 否 | sender_kind 为 user 时的公开用户引用。 |
| `senders[].sender_bot_uid` | `string` | 否 | sender_kind 为 bot 时的机器人 UID。 |
| `senders[].sender_name` | `string` | 否 | 当前账号可见的发送者显示名称快照；同一身份名称变化时会占用不同索引。 |
| `messages` | `array<object>` | 是 | 覆盖锚点消息前后的有界上下文，按会话顺序返回。 |
| `messages[].sequence` | `integer` | 是 | 消息在所属会话中的稳定顺序号；与 chat_session_uid 共同定位消息。 |
| `messages[].sender_index` | `integer` | 是 | 当前会话组 senders 数组的零基索引。 |
| `messages[].message_at` | `integer` | 是 | 消息业务时间，Unix 毫秒。 |
| `messages[].record_state` | `enum<string>` | 是 | 消息正文可用性；仅 available 返回正文，unavailable 不等同于 missing。 |
| `messages[].title` | `string` | 否 | 消息标题；内容不可见或不存在时省略。 |
| `messages[].text_content` | `string` | 否 | 用于分析的有界纯文本；需要完整当前正文时使用批量精确读取。 |
| `messages[].content_truncated` | `boolean` | 否 | 为 true 表示正文因公开接口长度限制被截断。 |
| `anchor_sequences` | `array<integer>` | 是 | 本次成功定位的输入消息顺序号。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `messages[].record_state` | `available` | 正文已读取，可以使用返回的标题和文本内容。 |
| `messages[].record_state` | `missing` | 对应正文不存在或已不再作为可见正文提供。 |
| `messages[].record_state` | `unavailable` | 本次无法取得正文，不代表正文不存在，可以稍后重新读取。 |
| `messages[].record_state` | `protected` | 正文存在但受保护，不返回标题和文本内容。 |
| `senders[].sender_kind` | `user` | 发送主体是真实用户；读取 sender_user_ref。 |
| `senders[].sender_kind` | `bot` | 发送主体是机器人；读取 sender_bot_uid。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "anchor_sequences": [
      42
    ],
    "chat_session_uid": "chat-session-1",
    "messages": [
      {
        "message_at": 1700001000000,
        "record_state": "available",
        "sender_index": 0,
        "sequence": 42,
        "text_content": "周五下午三点同步进度"
      }
    ],
    "senders": [
      {
        "sender_kind": "user",
        "sender_name": "小明",
        "sender_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 解析消息发送目标 {#resolveChatTargets}

`POST /api/v1/chat/targets/resolve`

按名称或人物引用批量解析允许发送消息的私聊或群聊目标。发送消息前使用该接口取得目标会话 UID。

Operation ID：`resolveChatTargets`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量发送目标解析项，1 到 10 项；单项调用也传一个元素。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].query` | `string` | 否 | 目标名称或自然语言描述；与 target_user_ref 必须且只能提供一个。 |
| `items[].target_user_ref` | `string` | 否 | 由人物解析或其他公开能力返回、可跨领域复用的用户引用。 |
| `items[].scopes` | `array<enum<string>>` | 否 | 发送目标解析范围；缺省包含全部可见范围。 |
| `items[].limit` | `integer` | 否 | 本页候选上限，1 到 5；缺省为 5。 |
| `items[].page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].scopes[]` | `contact` | 可作为联系人目录结果使用。 |
| `items[].scopes[]` | `private_chat` | 可作为私聊会话读取；pending 会话也可能属于此范围。 |
| `items[].scopes[]` | `group_chat` | 可作为群聊会话读取或发送。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/targets/resolve' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"target-1","target_user_ref":"usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","scopes":["private_chat"],"limit":5}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的消息发送目标解析结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].candidates` | `array<object>` | 是 | 当前可发送的 direct 或 group 目标候选。 |
| `items[].candidates[].chat_session_uid` | `string` | 是 | 聊天会话 UID；只用于聊天查询、上下文和发送能力，不能作为 Record 个人主题 UID。 |
| `items[].candidates[].kind` | `enum<string>` | 是 | 可发送目标形态。 |
| `items[].candidates[].scopes` | `array<enum<string>>` | 是 | 该发送目标可用于的范围。 |
| `items[].candidates[].display_name` | `string` | 是 | 当前账号可见的会话显示名称。 |
| `items[].candidates[].participant_user_ref` | `string` | 否 | 真人 direct 会话的唯一对端用户引用。 |
| `items[].has_more` | `boolean` | 是 | 是否还有下一页候选。 |
| `items[].next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].candidates[].kind` | `direct` | 可发送消息的私聊目标。 |
| `items[].candidates[].kind` | `group` | 可发送消息的群聊目标。 |
| `items[].candidates[].scopes[]` | `contact` | 可作为联系人目录结果使用。 |
| `items[].candidates[].scopes[]` | `private_chat` | 可作为私聊会话读取；pending 会话也可能属于此范围。 |
| `items[].candidates[].scopes[]` | `group_chat` | 可作为群聊会话读取或发送。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "candidates": [
          {
            "chat_session_uid": "chat-session-1",
            "display_name": "小明",
            "kind": "direct",
            "participant_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            "scopes": [
              "private_chat"
            ]
          }
        ],
        "has_more": false,
        "item_id": "target-1"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 创建真人私聊 {#createPrivateChats}

`POST /api/v1/chat/conversations/create-private`

用户明确要求联系指定真人时，创建或取得双方唯一私聊。输入公开用户引用；不加联系人、不发送消息、不打开 UI。Bot 专属会话由 Bot 工具定位。

Operation ID：`createPrivateChats`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 个明确的真人私聊目标；仅创建或取得私聊，不加联系人、不发送消息。 |
| `items[].item_id` | `string` | 是 | 本批唯一关联标识，最多 64 字节。 |
| `items[].target_user_ref` | `string` | 是 | 明确指定对方的公开用户引用，不能传 Bot UID。 |
| `items[].idempotency_key` | `string` | 是 | 稳定创建幂等键，最多 128 字符，仅字母、数字及 . _ : -；重试保持目标不变。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/conversations/create-private' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"one","target_user_ref":"usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","idempotency_key":"private-1"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的私聊创建结果；双方唯一会话可能早已存在。 |
| `items[].item_id` | `string` | 是 | 对应输入项。 |
| `items[].target_user_ref` | `string` | 是 | 指定对方的公开用户引用。 |
| `items[].chat_session_uid` | `string` | 否 | 创建或取得的真实私聊 UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项创建结果。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].status` | `succeeded` | 已创建或取得双方已有私聊。 |
| `items[].status` | `unknown` | 结果不确定，使用原参数核对或重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "chat_session_uid": "chat-1",
        "item_id": "one",
        "status": "succeeded",
        "target_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量发送聊天消息 {#sendChatMessages}

`POST /api/v1/chat/messages/send`

向已解析的私聊或群聊目标批量发送纯文本消息。每一项使用稳定幂等键，结果与输入项关联。

Operation ID：`sendChatMessages`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量发送项，1 到 10 项；整批先校验后执行。 |
| `items[].bot_mentions` | `array<object>` | 否 | 最多 10 个明确的群 Bot 提及；省略不主动指定 Bot。必须是当前群已安装 Bot，原样选择提及文本，重试保持不变。 |
| `items[].bot_mentions[].bot_uid` | `string` | 是 | 已安装的目标 Bot UID；不能按提及昵称推断身份。 |
| `items[].bot_mentions[].mention_text` | `string` | 是 | 原样复制正文中的完整提及文本，包含开头 @ 或全角＠；不修改正文。 |
| `items[].bot_mentions[].occurrence` | `null or integer` | 否 | 该提及文本第几次出现，从 1 开始。只出现一次可省略，多次出现必须指定。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].idempotency_key` | `string` | 是 | 调用方生成的稳定幂等键；同一业务发送重试必须复用，最多 128 字符，只能包含字母、数字及 . _ : -。 |
| `items[].chat_session_uid` | `string` | 是 | 目标会话 UID；必须使用目标解析能力返回的 direct 或 group 会话，不使用 pending 会话。 |
| `items[].text_content` | `string` | 是 | 要发送的纯文本内容，1 到 10000 字。 |
| `items[].send_at` | `integer` | 是 | 客户端业务发送时间，Unix 毫秒；重试必须保持不变。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/messages/send' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"message-1","idempotency_key":"send.project-sync.001","chat_session_uid":"chat-session-1","text_content":"周五下午三点同步进度","send_at":1700001000000}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的发送结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].chat_session_uid` | `string` | 是 | 实际发送到的聊天会话 UID。 |
| `items[].record_uid` | `string` | 是 | 新消息内容对应的记录 UID。 |
| `items[].sequence` | `integer` | 是 | 新消息在会话中的顺序号。 |
| `items[].target_kind` | `enum<string>` | 是 | 实际发送目标形态。 |
| `items[].target_name` | `string` | 否 | 发送目标的显示名称。 |
| `items[].audit_pending` | `boolean` | 否 | 为 true 表示消息已创建但仍在内容审核流程中。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].target_kind` | `direct` | 可发送消息的私聊目标。 |
| `items[].target_kind` | `group` | 可发送消息的群聊目标。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "chat_session_uid": "chat-session-1",
        "item_id": "message-1",
        "record_uid": "record-1",
        "sequence": 42,
        "target_kind": "direct",
        "target_name": "小明"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询群消息治理对象 {#queryGroupMessageModerationTargets}

`POST /api/v1/chat/messages/moderation/query`

当前有效群主按真人发送者和可选时间分页读取消息坐标与治理状态，不返回正文；空页仍检查 has_more。upper_sequence 是扫描上界，不是快照。

Operation ID：`queryGroupMessageModerationTargets`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `chat_session_uid` | `string` | 是 | 目标即我群聊 UID；当前有效群主可查询治理元信息。 |
| `sender_user_refs` | `array<string>` | 是 | 明确真人发送者，1 到 100 人；不包括借用该用户身份的机器人。 |
| `start_at` | `integer` | 否 | 消息时间下界（含），Unix 毫秒；省略从历史起点扫描。 |
| `end_at` | `integer` | 否 | 消息时间上界（不含），Unix 毫秒；省略扫描到首轮固定的 sequence 上界。 |
| `limit` | `integer` | 否 | 本页结果上限，1 到 500，默认 100；物理扫描有界，空页仍检查 has_more。 |
| `page_cursor` | `string` | 否 | 上页 next_page_cursor；保持群、发送人、时间条件不变。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/messages/moderation/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"chat_session_uid":"019d8590-ebb4-7232-90f2-000000000481","sender_user_refs":["usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"],"limit":100}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 按 sequence 递增的治理元信息，不包含受保护正文。 |
| `items[].sequence` | `integer` | 是 | 与本次 chat_session_uid 共同定位消息，可直接传给撤回工具。 |
| `items[].sender_user_ref` | `string` | 是 | 真人发送者的账号范围公开引用。 |
| `items[].message_at` | `integer` | 是 | 消息业务时间，Unix 毫秒。 |
| `items[].withdrawal_state` | `enum<string>` | 是 | 当前结构撤回状态。 |
| `items[].eligible` | `boolean` | 是 | 当前结构和发送者允许群主撤回；执行时仍重新鉴权。 |
| `items[].reason` | `enum<string>` | 否 | 不可操作原因。 |
| `upper_sequence` | `integer` | 是 | 本轮固定扫描上界，不是数据库快照；晚到提交需新一轮复查。 |
| `has_more` | `boolean` | 是 | 是否继续扫描；不能用本页条数推断完整性。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].reason` | `governance_conflict` | 当前角色或目标不允许该动作。 |
| `items[].reason` | `invalid_message_state` | 消息结构不支持撤回。 |
| `items[].reason` | `message_not_found` | 授权群内不存在该消息坐标。 |
| `items[].reason` | `member_unavailable` | 成员不存在或不可访问。 |
| `items[].reason` | `actor_not_active` | 操作者已不在群内。 |
| `items[].reason` | `group_unavailable` | 群不存在或已失效。 |
| `items[].reason` | `own_message` | 此入口不承接群主自己的消息。 |
| `items[].withdrawal_state` | `active` | 结构仍有效。 |
| `items[].withdrawal_state` | `withdrawn` | 结构已撤回。 |
| `items[].withdrawal_state` | `unavailable` | 结构不支持撤回。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "eligible": true,
        "message_at": 1700000000000,
        "sender_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
        "sequence": 1201,
        "withdrawal_state": "active"
      }
    ],
    "upper_sequence": 1201
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量撤回群消息 {#withdrawGroupMessages}

`POST /api/v1/chat/messages/withdraw`

用户明确要求撤回他人群消息时，直接传 chat_session_uid 与 sequence；不要求额外解析。原群时间线与群内搜索不再展示；本人个人搜索保留记录且不展示该群来源。不删除原始记录，不移出发送者。结果未知时同参数重试；原群时间线与群内搜索不再展示，本人个人搜索保留记录且不展示该群来源。

Operation ID：`withdrawGroupMessages`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 个明确消息坐标；批次允许部分成功。 |
| `items[].item_id` | `string` | 是 | 批次内唯一关联标识，UTF-8 最多 64 字节。 |
| `items[].chat_session_uid` | `string` | 是 | 目标即我群聊 UID。 |
| `items[].sequence` | `integer` | 是 | 群内稳定消息顺序号，必须为正数。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/messages/withdraw' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"message-1","chat_session_uid":"019d8590-ebb4-7232-90f2-000000000481","sequence":1201}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的逐项结果。成功表示事实成立并可恢复，不代表所有端已刷新。 |
| `items[].item_id` | `string` | 是 | 批次内唯一关联标识，UTF-8 最多 64 字节。 |
| `items[].chat_session_uid` | `string` | 是 | 目标即我群聊 UID。 |
| `items[].sequence` | `integer` | 是 | 群内稳定消息顺序号，必须为正数。 |
| `items[].status` | `enum<string>` | 是 | 单项业务结果。 |
| `items[].reason` | `enum<string>` | 否 | 确定性拒绝原因；基础设施失败不伪装成拒绝。 |
| `items[].changed` | `boolean` | 是 | 本次是否首次撤回；已撤回时为 false。 |
| `items[].withdrawn_at` | `integer` | 否 | 成功时的首次撤回版本时间，Unix 毫秒。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].reason` | `governance_conflict` | 当前角色或目标不允许该动作。 |
| `items[].reason` | `invalid_message_state` | 消息结构不支持撤回。 |
| `items[].reason` | `message_not_found` | 授权群内不存在该消息坐标。 |
| `items[].reason` | `member_unavailable` | 成员不存在或不可访问。 |
| `items[].reason` | `actor_not_active` | 操作者已不在群内。 |
| `items[].reason` | `group_unavailable` | 群不存在或已失效。 |
| `items[].reason` | `own_message` | 此入口不承接群主自己的消息。 |
| `items[].status` | `succeeded` | owner 事实已成立。 |
| `items[].status` | `rejected` | 确定性业务拒绝，见 reason。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "changed": true,
        "chat_session_uid": "019d8590-ebb4-7232-90f2-000000000481",
        "item_id": "message-1",
        "sequence": 1201,
        "status": "succeeded",
        "withdrawn_at": 1700000100000
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量读取群成员状态 {#batchGetGroupMembers}

`POST /api/v1/chat/members/batch-get`

当前有效群主按已知 user_ref 精确读取当前或历史成员状态；已知必要事实时无需重复读取。

Operation ID：`batchGetGroupMembers`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 个明确群成员；当前群主可读取已离群成员的状态。 |
| `items[].item_id` | `string` | 是 | 批次内唯一关联标识，UTF-8 最多 64 字节。 |
| `items[].chat_session_uid` | `string` | 是 | 目标即我群聊 UID。 |
| `items[].target_user_ref` | `string` | 是 | 已有或历史群成员的公开人物引用。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/members/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"member-1","chat_session_uid":"019d8590-ebb4-7232-90f2-000000000481","target_user_ref":"usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的精确成员状态。 |
| `items[].item_id` | `string` | 是 | 批次内唯一关联标识，UTF-8 最多 64 字节。 |
| `items[].chat_session_uid` | `string` | 是 | 目标即我群聊 UID。 |
| `items[].target_user_ref` | `string` | 是 | 已有或历史群成员的公开人物引用。 |
| `items[].found` | `boolean` | 是 | 是否存在该群的成员事实。 |
| `items[].member` | `null or object` | 否 | found 为 true 时的当前成员事实。 |
| `items[].member.membership_status` | `enum<string>` | 是 | 当前成员状态，与入群限制独立。 |
| `items[].member.role` | `enum<string>` | 是 | 成员角色；仅当前有效群主可执行本组治理能力。 |
| `items[].member.joined_at` | `integer` | 是 | 加入时间，Unix 毫秒。 |
| `items[].member.join_restricted` | `boolean` | 是 | 是否禁止未来入群，与当前是否在群内是独立事实。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].member.membership_status` | `active` | 当前在群内。 |
| `items[].member.membership_status` | `left` | 已主动离群。 |
| `items[].member.membership_status` | `removed` | 已被移出。 |
| `items[].member.role` | `owner` | 群主。 |
| `items[].member.role` | `admin` | 管理员。 |
| `items[].member.role` | `participant` | 普通成员。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "chat_session_uid": "019d8590-ebb4-7232-90f2-000000000481",
        "found": true,
        "item_id": "member-1",
        "member": {
          "join_restricted": true,
          "joined_at": 1700000000000,
          "membership_status": "removed",
          "role": "participant"
        },
        "target_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量移出群成员 {#removeGroupMembers}

`POST /api/v1/chat/members/remove`

用户明确要求移出时使用；prevent_rejoin=true 原子移出并限制，false 不解除已有限制。结果未知时先核对当前成员状态；重新入群后需重新确认操作意图。

Operation ID：`removeGroupMembers`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 个成员移出操作。 |
| `items[].item_id` | `string` | 是 | 批次内唯一关联标识，UTF-8 最多 64 字节。 |
| `items[].chat_session_uid` | `string` | 是 | 目标即我群聊 UID。 |
| `items[].target_user_ref` | `string` | 是 | 已有或历史群成员的公开人物引用。 |
| `items[].prevent_rejoin` | `boolean` | 否 | 显式 true 时原子移出并禁止再加入；缺省 false，不解除已有的限制。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/members/remove' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"member-1","chat_session_uid":"019d8590-ebb4-7232-90f2-000000000481","target_user_ref":"usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","prevent_rejoin":true}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的结果；消息治理与成员治理不互相代办。 |
| `items[].item_id` | `string` | 是 | 批次内唯一关联标识，UTF-8 最多 64 字节。 |
| `items[].chat_session_uid` | `string` | 是 | 目标即我群聊 UID。 |
| `items[].target_user_ref` | `string` | 是 | 已有或历史群成员的公开人物引用。 |
| `items[].status` | `enum<string>` | 是 | 单项业务结果。 |
| `items[].reason` | `enum<string>` | 否 | 确定性拒绝原因；基础设施失败不伪装成拒绝。 |
| `items[].member` | `null or object` | 否 | 成功时持久化的成员事实；失败不返回未经授权的数据。 |
| `items[].member.membership_status` | `enum<string>` | 是 | 当前成员状态，与入群限制独立。 |
| `items[].member.role` | `enum<string>` | 是 | 成员角色；仅当前有效群主可执行本组治理能力。 |
| `items[].member.joined_at` | `integer` | 是 | 加入时间，Unix 毫秒。 |
| `items[].member.join_restricted` | `boolean` | 是 | 是否禁止未来入群，与当前是否在群内是独立事实。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].member.membership_status` | `active` | 当前在群内。 |
| `items[].member.membership_status` | `left` | 已主动离群。 |
| `items[].member.membership_status` | `removed` | 已被移出。 |
| `items[].member.role` | `owner` | 群主。 |
| `items[].member.role` | `admin` | 管理员。 |
| `items[].member.role` | `participant` | 普通成员。 |
| `items[].reason` | `governance_conflict` | 当前角色或目标不允许该动作。 |
| `items[].reason` | `invalid_message_state` | 消息结构不支持撤回。 |
| `items[].reason` | `message_not_found` | 授权群内不存在该消息坐标。 |
| `items[].reason` | `member_unavailable` | 成员不存在或不可访问。 |
| `items[].reason` | `actor_not_active` | 操作者已不在群内。 |
| `items[].reason` | `group_unavailable` | 群不存在或已失效。 |
| `items[].reason` | `own_message` | 此入口不承接群主自己的消息。 |
| `items[].status` | `succeeded` | owner 事实已成立。 |
| `items[].status` | `rejected` | 确定性业务拒绝，见 reason。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "chat_session_uid": "019d8590-ebb4-7232-90f2-000000000481",
        "item_id": "member-1",
        "member": {
          "join_restricted": true,
          "joined_at": 1700000000000,
          "membership_status": "removed",
          "role": "participant"
        },
        "status": "succeeded",
        "target_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量设置入群限制 {#setGroupJoinRestrictions}

`POST /api/v1/chat/join-restrictions/set`

用户明确要求时设置 restricted=true 或解除 false；既不移出当前成员，也不自动拉人入群。结果未知时核对当前限制状态。

Operation ID：`setGroupJoinRestrictions`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 个独立入群限制设置。 |
| `items[].item_id` | `string` | 是 | 批次内唯一关联标识，UTF-8 最多 64 字节。 |
| `items[].chat_session_uid` | `string` | 是 | 目标即我群聊 UID。 |
| `items[].target_user_ref` | `string` | 是 | 已有或历史群成员的公开人物引用。 |
| `items[].restricted` | `boolean` | 是 | true 禁止未来入群，false 解除；不移出当前成员，也不自动邀请。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/join-restrictions/set' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"member-1","chat_session_uid":"019d8590-ebb4-7232-90f2-000000000481","target_user_ref":"usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","restricted":true}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的结果；消息治理与成员治理不互相代办。 |
| `items[].item_id` | `string` | 是 | 批次内唯一关联标识，UTF-8 最多 64 字节。 |
| `items[].chat_session_uid` | `string` | 是 | 目标即我群聊 UID。 |
| `items[].target_user_ref` | `string` | 是 | 已有或历史群成员的公开人物引用。 |
| `items[].status` | `enum<string>` | 是 | 单项业务结果。 |
| `items[].reason` | `enum<string>` | 否 | 确定性拒绝原因；基础设施失败不伪装成拒绝。 |
| `items[].member` | `null or object` | 否 | 成功时持久化的成员事实；失败不返回未经授权的数据。 |
| `items[].member.membership_status` | `enum<string>` | 是 | 当前成员状态，与入群限制独立。 |
| `items[].member.role` | `enum<string>` | 是 | 成员角色；仅当前有效群主可执行本组治理能力。 |
| `items[].member.joined_at` | `integer` | 是 | 加入时间，Unix 毫秒。 |
| `items[].member.join_restricted` | `boolean` | 是 | 是否禁止未来入群，与当前是否在群内是独立事实。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].member.membership_status` | `active` | 当前在群内。 |
| `items[].member.membership_status` | `left` | 已主动离群。 |
| `items[].member.membership_status` | `removed` | 已被移出。 |
| `items[].member.role` | `owner` | 群主。 |
| `items[].member.role` | `admin` | 管理员。 |
| `items[].member.role` | `participant` | 普通成员。 |
| `items[].reason` | `governance_conflict` | 当前角色或目标不允许该动作。 |
| `items[].reason` | `invalid_message_state` | 消息结构不支持撤回。 |
| `items[].reason` | `message_not_found` | 授权群内不存在该消息坐标。 |
| `items[].reason` | `member_unavailable` | 成员不存在或不可访问。 |
| `items[].reason` | `actor_not_active` | 操作者已不在群内。 |
| `items[].reason` | `group_unavailable` | 群不存在或已失效。 |
| `items[].reason` | `own_message` | 此入口不承接群主自己的消息。 |
| `items[].status` | `succeeded` | owner 事实已成立。 |
| `items[].status` | `rejected` | 确定性业务拒绝，见 reason。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "chat_session_uid": "019d8590-ebb4-7232-90f2-000000000481",
        "item_id": "member-1",
        "member": {
          "join_restricted": true,
          "joined_at": 1700000000000,
          "membership_status": "removed",
          "role": "participant"
        },
        "status": "succeeded",
        "target_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 列出群入群限制 {#listGroupJoinRestrictions}

`POST /api/v1/chat/join-restrictions/list`

当前有效群主分页读取受限制人物的 user_ref 和限制设置时间。已知目标时可直接调用设置能力。

Operation ID：`listGroupJoinRestrictions`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `chat_session_uid` | `string` | 是 | 当前有效群主拥有的群聊 UID。 |
| `limit` | `integer` | 否 | 每页 1 到 100 人，默认 30。 |
| `page_cursor` | `string` | 否 | 上页 next_page_cursor，仅可在同账号同群续页。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/chat/join-restrictions/list' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"chat_session_uid":"019d8590-ebb4-7232-90f2-000000000481","limit":30}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 当前有效入群限制，按设置时间倒序、人物稳定排序分页。 |
| `items[].display_name` | `string` | 是 | 当前群内昵称或公开名称；为空时资料不可用，不能猜测身份。名称可能重复，操作仍须使用 user_ref。 |
| `items[].user_ref` | `string` | 是 | 当前受限制成员的公开人物引用。 |
| `items[].restricted_at` | `integer` | 是 | 当前限制设置时间，Unix 毫秒。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "display_name": "群内小王",
        "restricted_at": 1700000100000,
        "user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 微信导入 {#rest-wechat_import}

### 查询微信导入会话 {#queryWechatImportConversations}

`POST /api/v1/wechat-import/conversations/query`

按最新消息时间分页读取微信导入会话；participant_user_ref 仅筛选当前账号已绑定该人的私聊，没有绑定返回空。不返回 wxid、外部会话 ID 或内部绑定字段。

Operation ID：`queryWechatImportConversations`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `participant_user_ref` | `string` | 否 | 已确认即我账号的用户引用；仅查当前账号已绑定该人的微信导入私聊。未绑定返回空，不按名称推断绑定。 |
| `start_at` | `integer` | 否 | 按最新消息时间筛选的下界（含），Unix 毫秒。 |
| `end_at` | `integer` | 否 | 按最新消息时间筛选的上界（不含），Unix 毫秒。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；继续时保持时间与参与人筛选不变。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/wechat-import/conversations/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"start_at":1700000000000,"end_at":1700086400000,"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 本页会话，按最新消息时间稳定倒序排列。 |
| `items[].conversation_uid` | `string` | 是 | 微信导入会话 UID；只用于微信导入会话、消息和群成员能力。 |
| `items[].kind` | `enum<string>` | 是 | 会话类型。 |
| `items[].display_name` | `string` | 是 | 依据导入会话快照生成的展示名。 |
| `items[].remark` | `string` | 否 | 导入快照中的用户可见备注名。 |
| `items[].nickname` | `string` | 否 | 导入快照中的会话昵称。 |
| `items[].avatar_url` | `string` | 否 | 已持久化的会话头像 URL。 |
| `items[].message_count` | `integer` | 是 | 当前快照中的消息总数。 |
| `items[].voice_count` | `integer` | 是 | 当前快照中的语音消息数。 |
| `items[].image_count` | `integer` | 是 | 当前快照中的图片消息数。 |
| `items[].emoji_count` | `integer` | 是 | 当前快照中的表情消息数。 |
| `items[].video_count` | `integer` | 是 | 当前快照中的视频消息数。 |
| `items[].first_sent_at` | `integer` | 否 | 最早消息发送时间，Unix 毫秒。 |
| `items[].last_sent_at` | `integer` | 否 | 最新消息发送时间，Unix 毫秒。 |
| `items[].imported_at` | `integer` | 否 | 最早导入时间，Unix 毫秒。 |
| `items[].version` | `integer` | 是 | 当前导入会话快照的只读版本。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].kind` | `direct` | 私聊会话。 |
| `items[].kind` | `group` | 群聊会话。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "conversation_uid": "wechat-session-1",
        "display_name": "项目讨论群",
        "emoji_count": 8,
        "first_sent_at": 1699000000000,
        "image_count": 24,
        "imported_at": 1700080000000,
        "kind": "group",
        "last_sent_at": 1700001000000,
        "message_count": 328,
        "version": 1700080000000,
        "video_count": 2,
        "voice_count": 12
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 解析微信导入会话 {#resolveWechatImportConversations}

`POST /api/v1/wechat-import/conversations/resolve`

按导入快照中的备注名、昵称或群名分页返回候选。名称不是账号绑定；取得 conversation_uid 后按消息时间读取消息。has_more 为 true 时继续翻页，空页不代表没有候选。

Operation ID：`resolveWechatImportConversations`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 待解析的微信导入会话名称，1 到 10 项；item_id 不重复。 |
| `items[].item_id` | `string` | 是 | 调用方关联标识，1 到 64 字节；结果与输入同序。 |
| `items[].query` | `string` | 是 | 备注名、昵称或群名，1–100 字符；字面匹配。 |
| `items[].kind` | `enum<string>` | 否 | 候选会话类型；省略则不限。 |
| `items[].limit` | `integer` | 否 | 本项每页最多候选数，1 到 10，缺省为 5。 |
| `items[].page_cursor` | `string` | 否 | 本项上一页的游标；保持名称与类型不变。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].kind` | `direct` | 私聊会话。 |
| `items[].kind` | `group` | 群聊会话。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/wechat-import/conversations/resolve' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"wechat-1","query":"项目群","kind":"group","limit":5}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 同序候选页，不推断即我账号身份。 |
| `items[].item_id` | `string` | 是 | 输入项标识。 |
| `items[].candidates` | `array<object>` | 是 | 本页可读导入会话候选。 |
| `items[].candidates[].conversation_uid` | `string` | 是 | 微信导入会话 UID；用于后续读取消息或会话详情。 |
| `items[].candidates[].kind` | `enum<string>` | 是 | 会话类型。 |
| `items[].candidates[].display_name` | `string` | 是 | 导入快照中的会话显示名。 |
| `items[].candidates[].remark` | `string` | 否 | 导入快照中的备注名。 |
| `items[].candidates[].nickname` | `string` | 否 | 导入快照中的昵称。 |
| `items[].candidates[].first_sent_at` | `integer` | 否 | 最早消息时间，Unix 毫秒。 |
| `items[].candidates[].last_sent_at` | `integer` | 否 | 最新消息时间，Unix 毫秒；查历史消息应在消息查询中指定时间。 |
| `items[].has_more` | `boolean` | 是 | 是否继续扫描；空页也可能为 true。 |
| `items[].next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].candidates[].kind` | `direct` | 私聊会话。 |
| `items[].candidates[].kind` | `group` | 群聊会话。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "candidates": [
          {
            "conversation_uid": "wechat-conversation-1",
            "display_name": "项目群",
            "kind": "group"
          }
        ],
        "has_more": false,
        "item_id": "wechat-1"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量读取微信导入会话 {#batchGetWechatImportConversations}

`POST /api/v1/wechat-import/conversations/batch-get`

按输入 UID 顺序精确读取微信导入会话快照。

Operation ID：`batchGetWechatImportConversations`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `conversation_uids` | `array<string>` | 是 | 要读取的微信导入会话 UID，1 到 20 个；结果与输入同序。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/wechat-import/conversations/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"conversation_uids":["wechat-session-1"]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入 UID 同序的读取结果。 |
| `items[].conversation_uid` | `string` | 是 | 输入的微信导入会话 UID。 |
| `items[].found` | `boolean` | 是 | 是否找到当前账号可读的会话快照。 |
| `items[].conversation` | `null or object` | 否 | found 为 true 时的完整会话事实。 |
| `items[].conversation.conversation_uid` | `string` | 是 | 微信导入会话 UID；只用于微信导入会话、消息和群成员能力。 |
| `items[].conversation.kind` | `enum<string>` | 是 | 会话类型。 |
| `items[].conversation.display_name` | `string` | 是 | 依据导入会话快照生成的展示名。 |
| `items[].conversation.remark` | `string` | 否 | 导入快照中的用户可见备注名。 |
| `items[].conversation.nickname` | `string` | 否 | 导入快照中的会话昵称。 |
| `items[].conversation.avatar_url` | `string` | 否 | 已持久化的会话头像 URL。 |
| `items[].conversation.message_count` | `integer` | 是 | 当前快照中的消息总数。 |
| `items[].conversation.voice_count` | `integer` | 是 | 当前快照中的语音消息数。 |
| `items[].conversation.image_count` | `integer` | 是 | 当前快照中的图片消息数。 |
| `items[].conversation.emoji_count` | `integer` | 是 | 当前快照中的表情消息数。 |
| `items[].conversation.video_count` | `integer` | 是 | 当前快照中的视频消息数。 |
| `items[].conversation.first_sent_at` | `integer` | 否 | 最早消息发送时间，Unix 毫秒。 |
| `items[].conversation.last_sent_at` | `integer` | 否 | 最新消息发送时间，Unix 毫秒。 |
| `items[].conversation.imported_at` | `integer` | 否 | 最早导入时间，Unix 毫秒。 |
| `items[].conversation.version` | `integer` | 是 | 当前导入会话快照的只读版本。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].conversation.kind` | `direct` | 私聊会话。 |
| `items[].conversation.kind` | `group` | 群聊会话。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "conversation": {
          "conversation_uid": "wechat-session-1",
          "display_name": "项目讨论群",
          "emoji_count": 8,
          "first_sent_at": 1699000000000,
          "image_count": 24,
          "imported_at": 1700080000000,
          "kind": "group",
          "last_sent_at": 1700001000000,
          "message_count": 328,
          "version": 1700080000000,
          "video_count": 2,
          "voice_count": 12
        },
        "conversation_uid": "wechat-session-1",
        "found": true
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询微信导入消息 {#queryWechatImportMessages}

`POST /api/v1/wechat-import/messages/query`

在一个微信导入会话内按时间和消息类型稳定分页；消息通过 sender_index 引用本页发送人。

Operation ID：`queryWechatImportMessages`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `conversation_uid` | `string` | 是 | 要读取消息的微信导入会话 UID。 |
| `kinds` | `array<enum<string>>` | 否 | 消息类型筛选。 |
| `start_at` | `integer` | 否 | 消息发送时间下界（含），Unix 毫秒。 |
| `end_at` | `integer` | 否 | 消息发送时间上界（不含），Unix 毫秒。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明消息游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `kinds[]` | `text` | 文本消息。 |
| `kinds[]` | `image` | 图片消息。 |
| `kinds[]` | `voice` | 语音消息。 |
| `kinds[]` | `video` | 视频消息。 |
| `kinds[]` | `emoji` | 表情消息。 |
| `kinds[]` | `call` | 通话记录消息。 |
| `kinds[]` | `location` | 位置消息。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/wechat-import/messages/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"conversation_uid":"wechat-session-1","kinds":["text","voice"],"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `conversation_uid` | `string` | 是 | 请求的微信导入会话 UID。 |
| `found` | `boolean` | 是 | 是否找到当前账号可读的会话快照。 |
| `senders` | `array<object>` | 是 | 本页去重后的发送人；消息通过 sender_index 引用。 |
| `senders[].display_name` | `string` | 是 | 导入快照中的发送人展示名；显示名不作为跨业务身份标识。 |
| `senders[].is_self` | `boolean` | 是 | 发送人是否属于当前用户导入的微信账号。 |
| `items` | `array<object>` | 是 | 本页消息，按发送时间稳定倒序排列。 |
| `items[].message_uid` | `string` | 是 | 微信导入消息 UID。 |
| `items[].sender_index` | `integer` | 是 | 发送人在本页 senders 数组中的零基索引。 |
| `items[].sent_at` | `integer` | 是 | 消息原始发送时间，Unix 毫秒。 |
| `items[].kind` | `enum<string>` | 是 | 消息类型。 |
| `items[].text_content` | `string` | 否 | 当前可读的消息正文；媒体消息可能为空。 |
| `items[].content_truncated` | `boolean` | 是 | 正文是否因开放平台单条长度限制被截断。 |
| `items[].has_media` | `boolean` | 是 | 是否存在已导入的媒体事实；不等价于返回可访问媒体地址。 |
| `items[].mime_type` | `string` | 否 | 已持久化的媒体 MIME 类型。 |
| `items[].media_size_bytes` | `integer` | 否 | 已持久化的媒体大小，字节。 |
| `items[].media_duration_ms` | `integer` | 否 | 音视频媒体时长，毫秒。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].kind` | `text` | 文本消息。 |
| `items[].kind` | `image` | 图片消息。 |
| `items[].kind` | `voice` | 语音消息。 |
| `items[].kind` | `video` | 视频消息。 |
| `items[].kind` | `emoji` | 表情消息。 |
| `items[].kind` | `call` | 通话记录消息。 |
| `items[].kind` | `location` | 位置消息。 |
| `items[].kind` | `other` | 其他已持久化类型。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "conversation_uid": "wechat-session-1",
    "found": true,
    "has_more": false,
    "items": [
      {
        "content_truncated": false,
        "has_media": false,
        "kind": "text",
        "message_uid": "64b64c2f9b8c1a2d3e4f5679",
        "sender_index": 0,
        "sent_at": 1700001000000,
        "text_content": "周五同步项目进度"
      }
    ],
    "senders": [
      {
        "display_name": "小明",
        "is_self": false
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量读取微信导入消息 {#batchGetWechatImportMessages}

`POST /api/v1/wechat-import/messages/batch-get`

按输入 UID 顺序精确读取微信导入消息和自包含发送人事实。

Operation ID：`batchGetWechatImportMessages`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `message_uids` | `array<string>` | 是 | 要读取的微信导入消息 UID，1 到 20 个；结果与输入同序。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/wechat-import/messages/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"message_uids":["64b64c2f9b8c1a2d3e4f5679"]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入 UID 同序的读取结果。 |
| `items[].message_uid` | `string` | 是 | 输入的微信导入消息 UID。 |
| `items[].found` | `boolean` | 是 | 是否找到当前账号可读的消息。 |
| `items[].message` | `null or object` | 否 | found 为 true 时的当前可读消息；正文仍需检查 content_truncated，媒体仅提供元数据。 |
| `items[].message.message_uid` | `string` | 是 | 微信导入消息 UID。 |
| `items[].message.conversation_uid` | `string` | 是 | 消息所属的微信导入会话 UID。 |
| `items[].message.sender` | `object` | 是 | 消息发送人。 |
| `items[].message.sender.display_name` | `string` | 是 | 导入快照中的发送人展示名；显示名不作为跨业务身份标识。 |
| `items[].message.sender.is_self` | `boolean` | 是 | 发送人是否属于当前用户导入的微信账号。 |
| `items[].message.sent_at` | `integer` | 是 | 消息原始发送时间，Unix 毫秒。 |
| `items[].message.kind` | `enum<string>` | 是 | 消息类型。 |
| `items[].message.text_content` | `string` | 否 | 当前可读的消息正文；媒体消息可能为空。 |
| `items[].message.content_truncated` | `boolean` | 是 | 正文是否被截断。 |
| `items[].message.has_media` | `boolean` | 是 | 是否存在已导入的媒体事实。 |
| `items[].message.mime_type` | `string` | 否 | 已持久化的媒体 MIME 类型。 |
| `items[].message.media_size_bytes` | `integer` | 否 | 已持久化的媒体大小，字节。 |
| `items[].message.media_duration_ms` | `integer` | 否 | 音视频媒体时长，毫秒。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].message.kind` | `text` | 文本消息。 |
| `items[].message.kind` | `image` | 图片消息。 |
| `items[].message.kind` | `voice` | 语音消息。 |
| `items[].message.kind` | `video` | 视频消息。 |
| `items[].message.kind` | `emoji` | 表情消息。 |
| `items[].message.kind` | `call` | 通话记录消息。 |
| `items[].message.kind` | `location` | 位置消息。 |
| `items[].message.kind` | `other` | 其他已持久化类型。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "found": true,
        "message": {
          "content_truncated": false,
          "conversation_uid": "wechat-session-1",
          "has_media": false,
          "kind": "text",
          "message_uid": "64b64c2f9b8c1a2d3e4f5679",
          "sender": {
            "display_name": "小明",
            "is_self": false
          },
          "sent_at": 1700001000000,
          "text_content": "周五同步项目进度"
        },
        "message_uid": "64b64c2f9b8c1a2d3e4f5679"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 列出微信导入群成员 {#listWechatImportGroupMembers}

`POST /api/v1/wechat-import/group-members/list`

稳定分页读取导入快照中的当前群成员，先判断 roster_state；不是微信实时成员或历史发言人集合。

Operation ID：`listWechatImportGroupMembers`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `conversation_uid` | `string` | 是 | 要读取当前 roster 的微信导入群会话 UID。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明群成员游标。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/wechat-import/group-members/list' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"conversation_uid":"wechat-session-1","limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `conversation_uid` | `string` | 是 | 请求的微信导入会话 UID。 |
| `roster_state` | `enum<string>` | 是 | 当前 roster 的可读状态。 |
| `items` | `array<object>` | 是 | 导入快照中的本页当前群成员，不是微信实时成员或历史发言人集合。 |
| `items[].display_name` | `string` | 是 | 群成员快照中的安全展示名。 |
| `items[].avatar_url` | `string` | 否 | 群成员快照中的头像 URL。 |
| `items[].is_friend` | `boolean` | 是 | 导入时该成员是否在好友列表中。 |
| `items[].is_self` | `boolean` | 是 | 该成员是否属于当前用户导入的微信账号。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `roster_state` | `available` | 当前群 roster 可读。 |
| `roster_state` | `unavailable` | 会话不可访问，或历史导入没有保存 roster 快照。 |
| `roster_state` | `not_group` | 该会话不是群聊。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "conversation_uid": "wechat-session-1",
    "has_more": false,
    "items": [
      {
        "display_name": "小明",
        "is_friend": true,
        "is_self": false
      }
    ],
    "roster_state": "available"
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 录音 {#rest-recording}

### 查询录音 {#queryRecordings}

`POST /api/v1/recordings/query`

按时间及可选的 speaker_user_refs、speaker_uids 读取当前账号录音元数据；人物条件取并集；时间按录音重叠范围筛选，有人物条件时需该人物在范围内有有效话语。order 缺省 asc，desc 从最新录音开始，不按关键词搜索。

Operation ID：`queryRecordings`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `order` | `enum<string>` | 否 | 录音开始时间排序，缺省 asc。 |
| `speaker_user_refs` | `array<string>` | 否 | 已确认账号的用户引用；与 speaker_uids 合计最多 20 个，任一目标匹配即可。 |
| `speaker_uids` | `array<string>` | 否 | 录音说话人候选返回的 UID；仅用于录音领域，与账号筛选取并集。 |
| `start_at` | `integer` | 否 | 时间范围下界（含），Unix 毫秒；按录音时间重叠筛选，有人物条件时要求该人物在范围内有有效话语；留空不限制。 |
| `end_at` | `integer` | 否 | 时间范围上界（不含），Unix 毫秒；语义同 start_at；留空不限制。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；继续时保持排序、时间与说话人筛选不变；空页且 has_more=true 时仍需翻页。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `order` | `asc` | 从最早录音开始读取。 |
| `order` | `desc` | 从最新录音开始读取。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/recordings/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"start_at":1700000000000,"end_at":1700086400000,"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 本页录音，按 order 指定方向以开始时间和录音 UID 稳定排序；可能少于 limit，空页仍须检查 has_more。 |
| `items[].recording_uid` | `string` | 是 | 录音 UID；只用于录音列表、批量读取和转写读取。 |
| `items[].name` | `string` | 否 | 录音的用户可见名称。 |
| `items[].start_at` | `integer` | 是 | 录音开始时间，Unix 毫秒。 |
| `items[].end_at` | `integer` | 否 | 录音已确认的结束时间，Unix 毫秒；尚未确认时为 0。 |
| `items[].duration_ms` | `integer` | 是 | 当前已确认的录音时长，毫秒。 |
| `items[].source` | `enum<string>` | 是 | 录音业务来源。 |
| `items[].ingest_origin` | `enum<string>` | 是 | 录音进入平台的入口。 |
| `items[].sealed` | `boolean` | 是 | 录音是否已经停止接收新的音频片段。 |
| `items[].transcript_state` | `enum<string>` | 是 | 规范转写状态。 |
| `items[].version` | `integer` | 是 | 录音的当前只读版本。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].ingest_origin` | `legacy_unknown` | 历史数据未记录入口。 |
| `items[].ingest_origin` | `user_client` | 用户客户端上传。 |
| `items[].ingest_origin` | `device` | 硬件设备回传。 |
| `items[].source` | `long` | 持续录音会话。 |
| `items[].source` | `file_upload` | 用户或设备导入的音频文件。 |
| `items[].transcript_state` | `ready` | 当前规范转写可读，未发现片段可读性缺口；不保证音频全时段均有文字或识别准确。 |
| `items[].transcript_state` | `partial` | 已有可读正文，但有片段仍在处理或不可读。 |
| `items[].transcript_state` | `processing` | 仍在处理。 |
| `items[].transcript_state` | `failed` | 处理失败且没有可读转写。 |
| `items[].transcript_state` | `unavailable` | 没有可读转写；不能据此推断静音、内容丢失或处理失败。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "duration_ms": 1800000,
        "end_at": 1700002800000,
        "ingest_origin": "user_client",
        "name": "项目访谈",
        "recording_uid": "64b64c2f9b8c1a2d3e4f5678",
        "sealed": true,
        "source": "long",
        "start_at": 1700001000000,
        "transcript_state": "ready",
        "version": 2
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 解析录音说话人 {#resolveRecordingSpeakers}

`POST /api/v1/recordings/speakers/resolve`

按当前账号的说话人标记名称分页返回候选，不搜索正文；选择 speaker_uid 后查询录音。has_more 为 true 时继续翻页，空页不代表没有候选。

Operation ID：`resolveRecordingSpeakers`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1–10 项说话人名称，item_id 不重复。 |
| `items[].item_id` | `string` | 是 | 调用方关联标识，1 到 64 字节；结果与输入同序。 |
| `items[].query` | `string` | 是 | 说话人标记名称，1–100 字符；字面匹配。 |
| `items[].limit` | `integer` | 否 | 本项每页最多候选数，1 到 10，缺省为 5。 |
| `items[].page_cursor` | `string` | 否 | 本项上一页的游标；保持名称不变。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/recordings/speakers/resolve' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"speaker-1","query":"张三","limit":5}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 同序候选页，不合并同名人物。 |
| `items[].item_id` | `string` | 是 | 输入项标识。 |
| `items[].candidates` | `array<object>` | 是 | 本页正式说话人候选；不同标记可关联同一 user_ref。 |
| `items[].candidates[].speaker_uid` | `string` | 是 | 当前账号录音领域的正式说话人 UID，不是录音内的 speaker_index。 |
| `items[].candidates[].display_name` | `string` | 是 | 当前说话人标记显示名。 |
| `items[].candidates[].user_ref` | `string` | 否 | 关联账号时返回；可展开该账号全部标记。 |
| `items[].has_more` | `boolean` | 是 | 是否继续扫描；空页也可能为 true。 |
| `items[].next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "candidates": [
          {
            "display_name": "张三",
            "speaker_uid": "64b64c2f9b8c1a2d3e4f5679"
          }
        ],
        "has_more": false,
        "item_id": "speaker-1"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量读取录音 {#batchGetRecordings}

`POST /api/v1/recordings/batch-get`

按输入 UID 顺序精确读取当前账号可见的录音元数据和转写状态。

Operation ID：`batchGetRecordings`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `recording_uids` | `array<string>` | 是 | 要读取的录音 UID，1 到 20 个；结果与输入同序。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/recordings/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"recording_uids":["64b64c2f9b8c1a2d3e4f5678"]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入 UID 同序的读取结果。 |
| `items[].recording_uid` | `string` | 是 | 输入的录音 UID。 |
| `items[].found` | `boolean` | 是 | 是否找到当前账号可读的录音。 |
| `items[].recording` | `null or object` | 否 | found 为 true 时的录音元数据和转写状态，不包含转写正文。 |
| `items[].recording.recording_uid` | `string` | 是 | 录音 UID；只用于录音列表、批量读取和转写读取。 |
| `items[].recording.name` | `string` | 否 | 录音的用户可见名称。 |
| `items[].recording.start_at` | `integer` | 是 | 录音开始时间，Unix 毫秒。 |
| `items[].recording.end_at` | `integer` | 否 | 录音已确认的结束时间，Unix 毫秒；尚未确认时为 0。 |
| `items[].recording.duration_ms` | `integer` | 是 | 当前已确认的录音时长，毫秒。 |
| `items[].recording.source` | `enum<string>` | 是 | 录音业务来源。 |
| `items[].recording.ingest_origin` | `enum<string>` | 是 | 录音进入平台的入口。 |
| `items[].recording.sealed` | `boolean` | 是 | 录音是否已经停止接收新的音频片段。 |
| `items[].recording.transcript_state` | `enum<string>` | 是 | 规范转写状态。 |
| `items[].recording.version` | `integer` | 是 | 录音的当前只读版本。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].recording.ingest_origin` | `legacy_unknown` | 历史数据未记录入口。 |
| `items[].recording.ingest_origin` | `user_client` | 用户客户端上传。 |
| `items[].recording.ingest_origin` | `device` | 硬件设备回传。 |
| `items[].recording.source` | `long` | 持续录音会话。 |
| `items[].recording.source` | `file_upload` | 用户或设备导入的音频文件。 |
| `items[].recording.transcript_state` | `ready` | 当前规范转写可读，未发现片段可读性缺口；不保证音频全时段均有文字或识别准确。 |
| `items[].recording.transcript_state` | `partial` | 已有可读正文，但有片段仍在处理或不可读。 |
| `items[].recording.transcript_state` | `processing` | 仍在处理。 |
| `items[].recording.transcript_state` | `failed` | 处理失败且没有可读转写。 |
| `items[].recording.transcript_state` | `unavailable` | 没有可读转写；不能据此推断静音、内容丢失或处理失败。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "found": true,
        "recording": {
          "duration_ms": 1800000,
          "end_at": 1700002800000,
          "ingest_origin": "user_client",
          "name": "项目访谈",
          "recording_uid": "64b64c2f9b8c1a2d3e4f5678",
          "sealed": true,
          "source": "long",
          "start_at": 1700001000000,
          "transcript_state": "ready",
          "version": 2
        },
        "recording_uid": "64b64c2f9b8c1a2d3e4f5678"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询录音转写 {#queryRecordingTranscript}

`POST /api/v1/recordings/transcript/query`

分页读取一条录音的规范转写；话语通过 speaker_index 引用本页说话人，正文完整性需结合 transcript_state 和 truncated 判断。

Operation ID：`queryRecordingTranscript`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `recording_uid` | `string` | 是 | 要读取转写的录音 UID。 |
| `limit` | `integer` | 否 | 本页最多返回项数，1 到 200；缺省为 100。bounded 按话语项计数，full 按文本片段计数，同一句可占多项。正文预算可能使本页提前结束，使用返回游标继续。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明转写游标。 |
| `text_mode` | `enum<string>` | 否 | 转写正文模式，缺省 bounded。 |
| `start_at` | `integer` | 否 | 显式话语时间窗下界（含），Unix 毫秒；按重叠选入完整原句，不继承列表条件。 |
| `end_at` | `integer` | 否 | 显式话语时间窗上界（不含），Unix 毫秒；省略不限制，不做字级裁剪。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `text_mode` | `bounded` | 每项为最多 4000 字符的话语；截断的句尾不可通过此模式补回。 |
| `text_mode` | `full` | 每项是话语的文本片段，可按字符坐标无损续读；limit 为本页片段数。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/recordings/transcript/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"recording_uid":"64b64c2f9b8c1a2d3e4f5678","start_at":1700001000000,"end_at":1700002800000,"text_mode":"full","limit":100}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `recording_uid` | `string` | 是 | 请求的录音 UID。 |
| `found` | `boolean` | 是 | 是否找到当前账号可读的录音。 |
| `transcript_state` | `enum<string>` | 否 | 规范转写状态。 |
| `speakers` | `array<object>` | 是 | 本页去重后的说话人；话语通过 speaker_index 引用。 |
| `speakers[].kind` | `enum<string>` | 是 | 说话人解析类型。 |
| `speakers[].display_name` | `string` | 是 | 录音中已解析的说话人显示名；显示名不作为跨业务身份标识。 |
| `speakers[].user_ref` | `string` | 否 | kind 为 user 时可跨领域复用的公开用户引用。 |
| `utterances` | `array<object>` | 是 | 本页规范转写话语项或 full 文本片段，按录音内话语时间及句内字符顺序排列。 |
| `utterances[].start_offset_ms` | `integer` | 是 | 话语相对录音开始的起点，毫秒。 |
| `utterances[].end_offset_ms` | `integer` | 是 | 话语相对录音开始的终点，毫秒。 |
| `utterances[].speaker_index` | `integer` | 是 | 说话人在本页 speakers 数组中的零基索引。 |
| `utterances[].text` | `string` | 是 | 规范转写正文，最多 4000 字符。 |
| `utterances[].truncated` | `boolean` | 是 | 当前项未容纳整句话语；bounded 游标跳到下句，full 可按字符坐标续读句尾。 |
| `utterances[].utterance_index` | `null or integer` | 否 | full 模式下的话语序号，同句话语的续片相同；仅用于同一录音、同次查询结果的片段拼接。 |
| `utterances[].text_start_offset` | `null or integer` | 否 | full 片段在整句话语中的 Unicode code point 起点（含）。 |
| `utterances[].text_end_offset` | `null or integer` | 否 | full 片段在整句话语中的 Unicode code point 终点（不含）。 |
| `utterances[].text_total_length` | `null or integer` | 否 | full 模式下整句话语的 Unicode code point 数；原话需按坐标及游标拼齐。 |
| `has_more` | `boolean` | 是 | 是否还有下一页转写。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `speakers[].kind` | `user` | 已解析为即我账号。 |
| `speakers[].kind` | `named` | 已命名但未关联即我账号。 |
| `speakers[].kind` | `anonymous` | 录音内稳定的匿名说话人。 |
| `speakers[].kind` | `unknown` | 无法确认身份。 |
| `transcript_state` | `ready` | 当前规范转写可读，未发现片段可读性缺口；不保证音频全时段均有文字或识别准确。 |
| `transcript_state` | `partial` | 已有可读正文，但有片段仍在处理或不可读。 |
| `transcript_state` | `processing` | 仍在处理。 |
| `transcript_state` | `failed` | 处理失败且没有可读转写。 |
| `transcript_state` | `unavailable` | 没有可读转写；不能据此推断静音、内容丢失或处理失败。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "found": true,
    "has_more": false,
    "recording_uid": "64b64c2f9b8c1a2d3e4f5678",
    "speakers": [
      {
        "display_name": "我",
        "kind": "user",
        "user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ],
    "transcript_state": "ready",
    "utterances": [
      {
        "end_offset_ms": 3200,
        "speaker_index": 0,
        "start_offset_ms": 1000,
        "text": "我们先确认下周的计划",
        "text_end_offset": 10,
        "text_start_offset": 0,
        "text_total_length": 10,
        "truncated": false,
        "utterance_index": 0
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询录音总结与时间线 {#queryRecordingSummaries}

`POST /api/v1/recordings/summaries/query`

按覆盖时间查询当前账号已保存的录音日总结和时间线版本元信息，不含正文，不触发生成。

Operation ID：`queryRecordingSummaries`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `kinds` | `array<enum<string>>` | 否 | 类型筛选；省略时包含日总结和时间线。 |
| `generation_states` | `array<enum<string>>` | 否 | 生成状态筛选；省略时包含全部状态。 |
| `start_at` | `integer` | 否 | 覆盖范围下界（含），Unix 毫秒；按时间重叠筛选，省略或为 0 时不限制下界。 |
| `end_at` | `integer` | 否 | 覆盖范围上界（不含），Unix 毫秒；省略或为 0 时不限制上界。 |
| `order` | `enum<string>` | 否 | 按覆盖开始时间、创建时间、UID 同向稳定排序；缺省 desc，不是按更新时间排序。 |
| `limit` | `integer` | 否 | 本页最多版本数，1–50，缺省 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的 next_page_cursor；续页保持筛选和排序不变。页间内容可能更新。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `generation_states[]` | `processing` | 生成中。 |
| `generation_states[]` | `completed` | 生成完成；读取正文时仍需检查 content_state。 |
| `generation_states[]` | `failed` | 生成失败。 |
| `kinds[]` | `daily_summary` | 录音日总结。 |
| `kinds[]` | `timeline` | 录音时间线。 |
| `order` | `asc` | 覆盖开始时间从早到晚，同时间按创建时间和 UID 升序。 |
| `order` | `desc` | 覆盖开始时间从晚到早，同时间按创建时间和 UID 降序。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/recordings/summaries/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"start_at":1699977600000,"end_at":1700064000000,"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 总结版本元信息，不含正文；同一时段可返回多个版本。 |
| `items[].summary_uid` | `string` | 是 | 已保存的日总结或时间线版本 UID，可用于读取正文。 |
| `items[].kind` | `enum<string>` | 是 | 总结类型。 |
| `items[].content_origin` | `enum<string>` | 是 | 内容来源。 |
| `items[].generation_state` | `enum<string>` | 是 | 总结生成状态。 |
| `items[].start_at` | `integer` | 是 | 总结覆盖开始时间，Unix 毫秒；范围内的话语不一定全部出现在总结中。 |
| `items[].end_at` | `integer` | 是 | 总结覆盖结束时间，Unix 毫秒。 |
| `items[].day_start_at` | `integer` | 是 | 总结所属本地日零点对应的 Unix 毫秒。 |
| `items[].created_at` | `integer` | 是 | 创建时间，Unix 毫秒。 |
| `items[].updated_at` | `integer` | 是 | 更新时间，Unix 毫秒；不是生成完成时间。 |
| `items[].model_display_name` | `string` | 否 | 生成时保存的用户可见模型展示名。 |
| `has_more` | `boolean` | 是 | 是否还有下一页版本。 |
| `next_page_cursor` | `string` | 否 | 下页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].content_origin` | `business_recording_summary` | 录音自动生成的日总结或时间线，供参考。 |
| `items[].generation_state` | `processing` | 生成中。 |
| `items[].generation_state` | `completed` | 生成完成；读取正文时仍需检查 content_state。 |
| `items[].generation_state` | `failed` | 生成失败。 |
| `items[].kind` | `daily_summary` | 录音日总结。 |
| `items[].kind` | `timeline` | 录音时间线。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "content_origin": "business_recording_summary",
        "created_at": 1700064000000,
        "day_start_at": 1699977600000,
        "end_at": 1700064000000,
        "generation_state": "completed",
        "kind": "daily_summary",
        "start_at": 1699977600000,
        "summary_uid": "64b64c2f9b8c1a2d3e4f5681",
        "updated_at": 1700064100000
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 读取录音总结与时间线 {#readRecordingSummary}

`POST /api/v1/recordings/summaries/read`

按 summary_uid 分页读取指定版本的原文和可读状态；不触发生成或修改内容。

Operation ID：`readRecordingSummary`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `summary_uid` | `string` | 是 | 要读取的总结版本 UID；已知时可直接读，无需先查询。 |
| `limit` | `integer` | 否 | 本页最多正文 Unicode code point 数，1–20000，缺省 10000。 |
| `page_cursor` | `string` | 否 | 上一页返回的 next_page_cursor；保持账号及 summary_uid 不变，版本内容更新后须从首页重读。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/recordings/summaries/read' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"summary_uid":"64b64c2f9b8c1a2d3e4f5681","limit":10000}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `summary_uid` | `string` | 是 | 请求的总结版本 UID。 |
| `found` | `boolean` | 是 | 是否找到当前账号可访问的总结；正文是否可读见 content_state。false 不区分不存在、已删除或无权访问。 |
| `summary` | `null or object` | 否 | found 为 true 时的总结元信息。 |
| `summary.summary_uid` | `string` | 是 | 已保存的日总结或时间线版本 UID，可用于读取正文。 |
| `summary.kind` | `enum<string>` | 是 | 总结类型。 |
| `summary.content_origin` | `enum<string>` | 是 | 内容来源。 |
| `summary.generation_state` | `enum<string>` | 是 | 总结生成状态。 |
| `summary.start_at` | `integer` | 是 | 总结覆盖开始时间，Unix 毫秒；范围内的话语不一定全部出现在总结中。 |
| `summary.end_at` | `integer` | 是 | 总结覆盖结束时间，Unix 毫秒。 |
| `summary.day_start_at` | `integer` | 是 | 总结所属本地日零点对应的 Unix 毫秒。 |
| `summary.created_at` | `integer` | 是 | 创建时间，Unix 毫秒。 |
| `summary.updated_at` | `integer` | 是 | 更新时间，Unix 毫秒；不是生成完成时间。 |
| `summary.model_display_name` | `string` | 否 | 生成时保存的用户可见模型展示名。 |
| `content_state` | `enum<string>` | 否 | 正文可读状态；found 为 false 时省略。 |
| `format` | `enum<string>` | 否 | 正文格式；JSON 分片需拼齐后解析，未识别格式按 text 返回。 |
| `text` | `string` | 是 | 总结原文片段；content_state 非 ready 或 found 为 false 时为空。 |
| `text_start_offset` | `integer` | 是 | 本片段在完整正文中的 Unicode code point 起点（含）。 |
| `text_end_offset` | `integer` | 是 | 本片段终点（不含），不保证自然段或 JSON 边界。 |
| `text_total_length` | `integer` | 是 | 完整正文的 Unicode code point 数；正文不可读时为 0。 |
| `has_more` | `boolean` | 是 | 是否还有同版本正文。 |
| `next_page_cursor` | `string` | 否 | 下页不透明正文游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `content_state` | `ready` | 正文可读，按 has_more 继续分页。 |
| `content_state` | `processing` | 仍在生成，当前没有正文。 |
| `content_state` | `failed` | 生成失败，当前没有正文。 |
| `content_state` | `unavailable` | 生成已结束，但没有可读正文。 |
| `format` | `markdown` | Markdown 文本。 |
| `format` | `json` | JSON 文本；单页不保证可解析。 |
| `format` | `text` | 按纯文本读取。 |
| `summary.content_origin` | `business_recording_summary` | 录音自动生成的日总结或时间线，供参考。 |
| `summary.generation_state` | `processing` | 生成中。 |
| `summary.generation_state` | `completed` | 生成完成；读取正文时仍需检查 content_state。 |
| `summary.generation_state` | `failed` | 生成失败。 |
| `summary.kind` | `daily_summary` | 录音日总结。 |
| `summary.kind` | `timeline` | 录音时间线。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "content_state": "ready",
    "format": "markdown",
    "found": true,
    "has_more": false,
    "summary": {
      "content_origin": "business_recording_summary",
      "created_at": 1700064000000,
      "day_start_at": 1699977600000,
      "end_at": 1700064000000,
      "generation_state": "completed",
      "kind": "daily_summary",
      "start_at": 1699977600000,
      "summary_uid": "64b64c2f9b8c1a2d3e4f5681",
      "updated_at": 1700064100000
    },
    "summary_uid": "64b64c2f9b8c1a2d3e4f5681",
    "text": "确认下周计划",
    "text_end_offset": 6,
    "text_start_offset": 0,
    "text_total_length": 6
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 通话 {#rest-call}

### 查询通话 {#queryCalls}

`POST /api/v1/calls/query`

按时间、方向、接通状态、媒体、结果、聊天会话或参与人稳定分页查询当前账号可见的通话。

Operation ID：`queryCalls`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `start_at` | `integer` | 否 | 通话创建时间下界（含），Unix 毫秒；缺省为结束时间前 30 天，时间窗最多 366 天。 |
| `end_at` | `integer` | 否 | 通话创建时间上界（含），Unix 毫秒；缺省或晚于当前时间时使用当前时间。 |
| `directions` | `array<enum<string>>` | 否 | 通话筛选枚举。 |
| `connection_states` | `array<enum<string>>` | 否 | 通话筛选枚举。 |
| `media_types` | `array<enum<string>>` | 否 | 通话筛选枚举。 |
| `results` | `array<enum<string>>` | 否 | 通话筛选枚举。 |
| `chat_session_uids` | `array<string>` | 否 | 可选聊天会话筛选，最多 20 个。 |
| `participant_user_refs` | `array<string>` | 否 | 最多 20 个参与人引用；任一目标匹配，与其他条件取交集。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；继续时保持筛选条件不变。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `connection_states[]` | `connected` | 通话已接通。 |
| `connection_states[]` | `not_connected` | 通话未接通。 |
| `directions[]` | `incoming` | 当前用户为被叫方。 |
| `directions[]` | `outgoing` | 当前用户为主叫方。 |
| `media_types[]` | `audio` | 音频通话。 |
| `media_types[]` | `video` | 视频通话。 |
| `results[]` | `normal_end` | 正常结束。 |
| `results[]` | `cancelled` | 发起方取消。 |
| `results[]` | `rejected` | 被叫方拒绝。 |
| `results[]` | `not_answered` | 无人接听。 |
| `results[]` | `busy` | 对方忙线。 |
| `results[]` | `offline` | 对方离线。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/calls/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"start_at":1700000000000,"end_at":1700086400000,"directions":["outgoing"],"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 本页通话，按创建时间和通话 UID 稳定倒序排列。 |
| `items[].call_uid` | `string` | 是 | 通话 UID；只用于通话列表、批量读取和转写读取。 |
| `items[].started_at` | `string` | 是 | 通话开始时间，RFC 3339 UTC。 |
| `items[].duration_ms` | `integer` | 是 | 已记录的通话时长，毫秒；从接通时间计算，缺少接通时间时从开始时间计算；结束时间缺失或无效时为 0。 |
| `items[].direction` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].connection_state` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].media_type` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].result` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].participants` | `array<object>` | 是 | 当前通话中最多 50 位可见参与人。 |
| `items[].participants[].user_ref` | `string` | 是 | 可跨人物、聊天与其他开放能力复用的公开用户引用。 |
| `items[].participants[].display_name` | `string` | 是 | 当前查看者可见的参与人名称。 |
| `items[].participants[].role` | `enum<string>` | 是 | 通话参与人角色。 |
| `items[].participants[].connected` | `boolean` | 是 | 该参与人是否接通过本通通话。 |
| `items[].participants[].is_self` | `boolean` | 是 | 该参与人是否为当前用户。 |
| `items[].participants_truncated` | `boolean` | 是 | 参与人数是否超过返回上限；为 true 时 participants 不是完整名单。 |
| `items[].transcript_state` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].summary_state` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].summary` | `null or object` | 否 | summary_state 为 ready 时的摘要。 |
| `items[].summary.text` | `string` | 是 | 通话摘要正文。 |
| `items[].summary.source` | `enum<string>` | 是 | 通话摘要来源。 |
| `items[].summary.truncated` | `boolean` | 是 | 摘要是否因长度限制被截断。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].connection_state` | `connected` | 通话已接通。 |
| `items[].connection_state` | `not_connected` | 通话未接通。 |
| `items[].direction` | `incoming` | 当前用户为被叫方。 |
| `items[].direction` | `outgoing` | 当前用户为主叫方。 |
| `items[].media_type` | `audio` | 音频通话。 |
| `items[].media_type` | `video` | 视频通话。 |
| `items[].participants[].role` | `caller` | 主叫方。 |
| `items[].participants[].role` | `callee` | 被叫方。 |
| `items[].result` | `normal_end` | 正常结束。 |
| `items[].result` | `cancelled` | 发起方取消。 |
| `items[].result` | `rejected` | 被叫方拒绝。 |
| `items[].result` | `not_answered` | 无人接听。 |
| `items[].result` | `busy` | 对方忙线。 |
| `items[].result` | `offline` | 对方离线。 |
| `items[].result` | `unknown` | 历史或扩展结果。 |
| `items[].summary.source` | `template` | 当前模板摘要。 |
| `items[].summary.source` | `legacy` | 历史摘要。 |
| `items[].summary_state` | `ready` | 摘要可读。 |
| `items[].summary_state` | `processing` | 仍在处理。 |
| `items[].summary_state` | `failed` | 处理失败。 |
| `items[].summary_state` | `unavailable` | 没有可用摘要。 |
| `items[].transcript_state` | `ready` | 转写可读。 |
| `items[].transcript_state` | `processing` | 仍在处理。 |
| `items[].transcript_state` | `failed` | 处理失败。 |
| `items[].transcript_state` | `unavailable` | 没有可用转写。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "call_uid": "64b64c2f9b8c1a2d3e4f5680",
        "connection_state": "connected",
        "direction": "outgoing",
        "duration_ms": 600000,
        "media_type": "audio",
        "participants": [
          {
            "connected": true,
            "display_name": "我",
            "is_self": true,
            "role": "caller",
            "user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
          }
        ],
        "participants_truncated": false,
        "result": "normal_end",
        "started_at": "2023-11-14T22:30:00Z",
        "summary": {
          "source": "template",
          "text": "确认了下周计划",
          "truncated": false
        },
        "summary_state": "ready",
        "transcript_state": "ready"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量读取通话 {#batchGetCalls}

`POST /api/v1/calls/batch-get`

按输入 UID 顺序精确读取通话概览、参与人、摘要和处理状态。

Operation ID：`batchGetCalls`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `call_uids` | `array<string>` | 是 | 要读取的通话 UID，1 到 20 个；结果与输入同序。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/calls/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"call_uids":["64b64c2f9b8c1a2d3e4f5680"]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入 UID 同序的读取结果。 |
| `items[].call_uid` | `string` | 是 | 输入的通话 UID。 |
| `items[].found` | `boolean` | 是 | 是否找到当前账号可读的通话。 |
| `items[].call` | `null or object` | 否 | found 为 true 时的通话概览、参与人、摘要和状态，不包含转写正文。 |
| `items[].call.call_uid` | `string` | 是 | 通话 UID；只用于通话列表、批量读取和转写读取。 |
| `items[].call.started_at` | `string` | 是 | 通话开始时间，RFC 3339 UTC。 |
| `items[].call.duration_ms` | `integer` | 是 | 已记录的通话时长，毫秒；从接通时间计算，缺少接通时间时从开始时间计算；结束时间缺失或无效时为 0。 |
| `items[].call.direction` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].call.connection_state` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].call.media_type` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].call.result` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].call.participants` | `array<object>` | 是 | 当前通话中最多 50 位可见参与人。 |
| `items[].call.participants[].user_ref` | `string` | 是 | 可跨人物、聊天与其他开放能力复用的公开用户引用。 |
| `items[].call.participants[].display_name` | `string` | 是 | 当前查看者可见的参与人名称。 |
| `items[].call.participants[].role` | `enum<string>` | 是 | 通话参与人角色。 |
| `items[].call.participants[].connected` | `boolean` | 是 | 该参与人是否接通过本通通话。 |
| `items[].call.participants[].is_self` | `boolean` | 是 | 该参与人是否为当前用户。 |
| `items[].call.participants_truncated` | `boolean` | 是 | 参与人数是否超过返回上限；为 true 时 participants 不是完整名单。 |
| `items[].call.transcript_state` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].call.summary_state` | `enum<string>` | 是 | 通话事实枚举。 |
| `items[].call.summary` | `null or object` | 否 | summary_state 为 ready 时的摘要。 |
| `items[].call.summary.text` | `string` | 是 | 通话摘要正文。 |
| `items[].call.summary.source` | `enum<string>` | 是 | 通话摘要来源。 |
| `items[].call.summary.truncated` | `boolean` | 是 | 摘要是否因长度限制被截断。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].call.connection_state` | `connected` | 通话已接通。 |
| `items[].call.connection_state` | `not_connected` | 通话未接通。 |
| `items[].call.direction` | `incoming` | 当前用户为被叫方。 |
| `items[].call.direction` | `outgoing` | 当前用户为主叫方。 |
| `items[].call.media_type` | `audio` | 音频通话。 |
| `items[].call.media_type` | `video` | 视频通话。 |
| `items[].call.participants[].role` | `caller` | 主叫方。 |
| `items[].call.participants[].role` | `callee` | 被叫方。 |
| `items[].call.result` | `normal_end` | 正常结束。 |
| `items[].call.result` | `cancelled` | 发起方取消。 |
| `items[].call.result` | `rejected` | 被叫方拒绝。 |
| `items[].call.result` | `not_answered` | 无人接听。 |
| `items[].call.result` | `busy` | 对方忙线。 |
| `items[].call.result` | `offline` | 对方离线。 |
| `items[].call.result` | `unknown` | 历史或扩展结果。 |
| `items[].call.summary.source` | `template` | 当前模板摘要。 |
| `items[].call.summary.source` | `legacy` | 历史摘要。 |
| `items[].call.summary_state` | `ready` | 摘要可读。 |
| `items[].call.summary_state` | `processing` | 仍在处理。 |
| `items[].call.summary_state` | `failed` | 处理失败。 |
| `items[].call.summary_state` | `unavailable` | 没有可用摘要。 |
| `items[].call.transcript_state` | `ready` | 转写可读。 |
| `items[].call.transcript_state` | `processing` | 仍在处理。 |
| `items[].call.transcript_state` | `failed` | 处理失败。 |
| `items[].call.transcript_state` | `unavailable` | 没有可用转写。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "call": {
          "call_uid": "64b64c2f9b8c1a2d3e4f5680",
          "connection_state": "connected",
          "direction": "outgoing",
          "duration_ms": 600000,
          "media_type": "audio",
          "participants": [
            {
              "connected": true,
              "display_name": "我",
              "is_self": true,
              "role": "caller",
              "user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
            }
          ],
          "participants_truncated": false,
          "result": "normal_end",
          "started_at": "2023-11-14T22:30:00Z",
          "summary_state": "unavailable",
          "transcript_state": "ready"
        },
        "call_uid": "64b64c2f9b8c1a2d3e4f5680",
        "found": true
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询通话转写 {#queryCallTranscript}

`POST /api/v1/calls/transcript/query`

分页读取通话的规范转写；participant_side 不代表参与人本人，正文完整性需结合 transcript_state 和 truncated 判断。

Operation ID：`queryCallTranscript`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `call_uid` | `string` | 是 | 要读取转写的通话 UID。 |
| `limit` | `integer` | 否 | 本页最多返回句数，1 到 500；缺省为 100。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明转写游标。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/calls/transcript/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"call_uid":"64b64c2f9b8c1a2d3e4f5680","limit":100}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `call_uid` | `string` | 是 | 请求的通话 UID。 |
| `found` | `boolean` | 是 | 是否找到当前账号可读的通话。 |
| `transcript_state` | `enum<string>` | 否 | 通话转写状态。 |
| `speakers` | `array<object>` | 是 | 本页去重后的说话人。 |
| `speakers[].display_name` | `string` | 是 | 通话中已解析的说话人显示名；显示名不作为跨业务身份标识。 |
| `speakers[].resolution` | `enum<string>` | 是 | 说话人归因精度。 |
| `speakers[].user_ref` | `string` | 否 | resolution 为 participant 时的公开用户引用；participant_side 不代表具体本人，因此省略。 |
| `utterances` | `array<object>` | 是 | 本页通话转写，按时间升序排列。 |
| `utterances[].start_ms` | `integer` | 是 | 话语相对通话录制开始的起点，毫秒。 |
| `utterances[].end_ms` | `integer` | 是 | 话语相对通话录制开始的终点，毫秒。 |
| `utterances[].speaker_index` | `integer` | 是 | 说话人在本页 speakers 数组中的零基索引。 |
| `utterances[].text` | `string` | 是 | 通话转写正文。 |
| `utterances[].truncated` | `boolean` | 是 | 正文是否因长度限制被截断。 |
| `has_more` | `boolean` | 是 | 是否还有下一页转写。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明转写游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `speakers[].resolution` | `participant` | 精确归因到通话参与人。 |
| `speakers[].resolution` | `participant_side` | 只归因到参与人一侧，不能视为参与人本人。 |
| `speakers[].resolution` | `unknown` | 无法归因。 |
| `transcript_state` | `ready` | 转写可读。 |
| `transcript_state` | `processing` | 仍在处理。 |
| `transcript_state` | `failed` | 处理失败。 |
| `transcript_state` | `unavailable` | 没有可用转写。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "call_uid": "64b64c2f9b8c1a2d3e4f5680",
    "found": true,
    "has_more": false,
    "speakers": [
      {
        "display_name": "我",
        "resolution": "participant",
        "user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ],
    "transcript_state": "ready",
    "utterances": [
      {
        "end_ms": 3200,
        "speaker_index": 0,
        "start_ms": 1000,
        "text": "我们先确认下周的计划",
        "truncated": false
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 记录 {#rest-record}

### 列出记录主题 {#listRecordContainers}

`POST /api/v1/record/containers/list`

分页列出当前账号拥有且有效的个人主题，并返回稳定的主题 UID、父主题 UID 和展示路径。

Operation ID：`listRecordContainers`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 100；缺省为 50。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/record/containers/list' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"limit":50}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 当前账号拥有且有效的个人主题容器。 |
| `items[].container` | `object` | 是 | 真实个人主题容器。 |
| `items[].container.kind` | `enum<string>` | 是 | 主题候选固定为 topic，并携带 topic_uid。 |
| `items[].container.topic_uid` | `string` | 是 | Record 个人主题 UID，可直接传给接受 topic 容器的记录能力。 |
| `items[].parent_topic_uid` | `string` | 否 | 父级个人主题 UID；根主题省略。 |
| `items[].title` | `string` | 是 | 个人主题标题。 |
| `items[].display_path` | `string` | 是 | 便于用户识别候选的展示路径。 |
| `items[].created_at` | `integer` | 否 | 个人主题创建时间，Unix 毫秒。 |
| `has_more` | `boolean` | 是 | 是否还有下一页主题。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].container.kind` | `topic` | Record 个人主题容器，读取 topic_uid。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "container": {
          "kind": "topic",
          "topic_uid": "topic-1"
        },
        "created_at": 1700000000000,
        "display_path": "个人主题 / 工作",
        "title": "工作"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 解析记录主题 {#resolveRecordContainers}

`POST /api/v1/record/containers/resolve`

按名称批量查找可用于记录和安排的个人主题。该接口只解析 Record 个人主题，不解析私聊或群聊。

Operation ID：`resolveRecordContainers`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量容器解析项，1 到 10 项；单项调用也传一个元素。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].query` | `string` | 是 | 当前用户拥有且有效的 Record 个人主题名称或层级路径，最多 100 字；不解析私聊或群聊。 |
| `items[].limit` | `integer` | 否 | 本页候选上限，1 到 10；缺省为 5。 |
| `items[].page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/record/containers/resolve' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"container-1","query":"工作","limit":5}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的记录容器解析结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].candidates` | `array<object>` | 是 | 当前账号拥有的 Record 个人主题候选；container.topic_uid 可用于记录容器或安排的 topic_uid。 |
| `items[].candidates[].container` | `object` | 是 | 真实个人主题容器。 |
| `items[].candidates[].container.kind` | `enum<string>` | 是 | 主题候选固定为 topic，并携带 topic_uid。 |
| `items[].candidates[].container.topic_uid` | `string` | 是 | Record 个人主题 UID，可直接传给接受 topic 容器的记录能力。 |
| `items[].candidates[].parent_topic_uid` | `string` | 否 | 父级个人主题 UID；根主题省略。 |
| `items[].candidates[].title` | `string` | 是 | 个人主题标题。 |
| `items[].candidates[].display_path` | `string` | 是 | 便于用户识别候选的展示路径。 |
| `items[].candidates[].created_at` | `integer` | 否 | 个人主题创建时间，Unix 毫秒。 |
| `items[].has_more` | `boolean` | 是 | 是否还有下一页候选。 |
| `items[].next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].candidates[].container.kind` | `topic` | Record 个人主题容器，读取 topic_uid。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "candidates": [
          {
            "container": {
              "kind": "topic",
              "topic_uid": "topic-1"
            },
            "created_at": 1700000000000,
            "display_path": "个人主题 / 工作",
            "title": "工作"
          }
        ],
        "has_more": false,
        "item_id": "container-1"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询记录时间线 {#queryRecordTimeline}

`POST /api/v1/record/timeline/query`

按业务时间分页读取当前账号的记录；可按创建人、来源和当前主容器精确筛选，继续查询时原样传回 next_page_cursor。

Operation ID：`queryRecordTimeline`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `start_at` | `integer` | 否 | 时间线起始时间（含），Unix 毫秒；留空不限制。 |
| `end_at` | `integer` | 否 | 时间线结束时间（含），Unix 毫秒；留空不限制。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |
| `order` | `enum<string>` | 否 | 发送时间排序方向；缺省为 desc。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 150；缺省为 50。 |
| `creator_user_refs` | `array<string>` | 否 | 仅返回这些人物创建的记录，最多 100 人；引用来自人物解析或其他公开能力。 |
| `origins` | `array<enum<string>>` | 否 | 记录来源筛选；缺省包含全部来源。 |
| `container` | `null or object` | 否 | 可选当前主容器筛选；topic 精确限定个人主题，unclassified 只返回当前未分类记录。 |
| `container.kind` | `enum<string>` | 是 | 容器形态；topic 携带 topic_uid，unclassified 不携带实体 UID。 |
| `container.topic_uid` | `string` | 否 | Record 个人主题 UID；仅在 kind 为 topic 时提供，不能传聊天会话 UID。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `container.kind` | `topic` | Record 个人主题容器，必须同时提供 topic_uid。 |
| `container.kind` | `unclassified` | 未分类容器，不携带任何实体 UID。 |
| `order` | `asc` | 按 send_at 从早到晚返回。 |
| `order` | `desc` | 按 send_at 从晚到早返回；这是缺省顺序。 |
| `origins[]` | `self` | 由当前账号直接形成的记录。 |
| `origins[]` | `topic` | 来源于 Record 个人主题的记录。 |
| `origins[]` | `private_chat` | 来源于私聊的记录。 |
| `origins[]` | `group_chat` | 来源于群聊的记录。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/record/timeline/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"order":"desc","limit":50,"creator_user_refs":["usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"],"container":{"kind":"topic","topic_uid":"topic-1"}}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 按指定顺序返回的记录。 |
| `items[].record_uid` | `string` | 是 | 记录 UID；只用于记录查询、更新、移动、删除或安排关联，不能作为聊天会话或个人主题 UID。 |
| `items[].state` | `enum<string>` | 是 | 记录可见性；仅 available 保证返回正文。 |
| `items[].creator_user_ref` | `string` | 否 | 记录创建人的公开用户引用。 |
| `items[].origin` | `enum<string>` | 否 | 记录形成来源。 |
| `items[].title` | `string` | 否 | 记录标题；内容不可见或不存在时省略。 |
| `items[].text_content` | `string` | 否 | 记录纯文本正文；内容不可见或不存在时省略。 |
| `items[].send_at` | `integer` | 否 | 记录业务时间，Unix 毫秒。 |
| `items[].version` | `integer` | 否 | 记录当前版本号，用于防止更新或删除覆盖并发修改。 |
| `items[].container` | `null or object` | 否 | 当前主容器；batch_get 对可用记录保证返回，其他查询可能省略。 |
| `items[].container.kind` | `enum<string>` | 是 | 容器形态；topic 携带 topic_uid，unclassified 不携带实体 UID。 |
| `items[].container.topic_uid` | `string` | 否 | Record 个人主题 UID；仅在 kind 为 topic 时提供，不能传聊天会话 UID。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |
| `has_more` | `boolean` | 是 | 是否还有下一页记录。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].container.kind` | `topic` | Record 个人主题容器，必须同时提供 topic_uid。 |
| `items[].container.kind` | `unclassified` | 未分类容器，不携带任何实体 UID。 |
| `items[].origin` | `self` | 由当前账号直接形成的记录。 |
| `items[].origin` | `topic` | 来源于 Record 个人主题的记录。 |
| `items[].origin` | `private_chat` | 来源于私聊的记录。 |
| `items[].origin` | `group_chat` | 来源于群聊的记录。 |
| `items[].state` | `available` | 记录有效且正文可见，可以读取标题和文本内容。 |
| `items[].state` | `protected` | 记录存在但正文受保护，不返回标题和文本内容。 |
| `items[].state` | `deleted` | 记录已经软删除，只返回可公开的状态事实。 |
| `items[].state` | `hidden` | 记录处于隐藏状态，只返回可公开的状态事实。 |
| `items[].state` | `missing` | 当前账号范围内没有可返回的记录事实。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "container": {
          "kind": "topic",
          "topic_uid": "topic-1"
        },
        "creator_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
        "origin": "self",
        "record_uid": "record-1",
        "send_at": 1700001000000,
        "state": "available",
        "text_content": "周五下午三点同步进度",
        "title": "项目同步",
        "version": 1
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 搜索记录 {#searchRecords}

`POST /api/v1/record/search`

按关键词搜索当前账号的记录，可按创建人精确筛选；返回命中字段、摘要和来源，触发容量保护时返回收窄原因而非部分结果。

Operation ID：`searchRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `keyword` | `string` | 是 | 搜索关键词，1 到 100 字。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |
| `start_date` | `string` | 否 | 可选开始日期，格式 YYYY-MM-DD；提供任一日期时必须同时提供 timezone。 |
| `end_date` | `string` | 否 | 可选结束日期，格式 YYYY-MM-DD，不能早于 start_date；提供任一日期时必须同时提供 timezone。 |
| `timezone` | `string` | 否 | 解释日期边界的 IANA 时区，例如 Asia/Shanghai；仅在提供 start_date 或 end_date 时填写。 |
| `creator_user_refs` | `array<string>` | 否 | 仅返回这些人物创建的记录，最多 100 人；引用来自人物解析或其他公开能力。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/record/search' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"keyword":"同步进度","creator_user_refs":["usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"],"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 本页搜索命中；refinement_required 为 true 时为空。 |
| `items[].record` | `object` | 是 | 命中的记录。 |
| `items[].record.record_uid` | `string` | 是 | 记录 UID；只用于记录查询、更新、移动、删除或安排关联，不能作为聊天会话或个人主题 UID。 |
| `items[].record.state` | `enum<string>` | 是 | 记录可见性；仅 available 保证返回正文。 |
| `items[].record.creator_user_ref` | `string` | 否 | 记录创建人的公开用户引用。 |
| `items[].record.origin` | `enum<string>` | 否 | 记录形成来源。 |
| `items[].record.title` | `string` | 否 | 记录标题；内容不可见或不存在时省略。 |
| `items[].record.text_content` | `string` | 否 | 记录纯文本正文；内容不可见或不存在时省略。 |
| `items[].record.send_at` | `integer` | 否 | 记录业务时间，Unix 毫秒。 |
| `items[].record.version` | `integer` | 否 | 记录当前版本号，用于防止更新或删除覆盖并发修改。 |
| `items[].record.container` | `null or object` | 否 | 当前主容器；batch_get 对可用记录保证返回，其他查询可能省略。 |
| `items[].record.container.kind` | `enum<string>` | 是 | 容器形态；topic 携带 topic_uid，unclassified 不携带实体 UID。 |
| `items[].record.container.topic_uid` | `string` | 否 | Record 个人主题 UID；仅在 kind 为 topic 时提供，不能传聊天会话 UID。 |
| `items[].source` | `object` | 是 | 记录来源；根据 kind 读取对应的实体标识字段。 |
| `items[].source.kind` | `enum<string>` | 是 | 搜索命中的来源形态。 |
| `items[].source.topic_uid` | `string` | 否 | kind 为 topic 时的 Record 个人主题 UID。 |
| `items[].source.chat_session_uid` | `string` | 否 | kind 为 chat 时的聊天会话 UID。 |
| `items[].matched_fields` | `array<enum<string>>` | 是 | 搜索命中的记录字段。 |
| `items[].snippet` | `string` | 是 | 包含关键词附近内容的短摘要。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回 page_cursor。 |
| `has_more` | `boolean` | 是 | 是否还有下一页命中。 |
| `refinement_required` | `boolean` | 是 | 为 true 表示当前查询条件触发容量保护，需要按 refinement_reasons 收窄后重新搜索。 |
| `refinement_reasons` | `array<enum<string>>` | 否 | 容量保护原因；应收窄条件后重新搜索，不用于翻页。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].matched_fields[]` | `title` | 关键词命中记录标题。 |
| `items[].matched_fields[]` | `body` | 关键词命中记录正文。 |
| `items[].record.container.kind` | `topic` | Record 个人主题容器，必须同时提供 topic_uid。 |
| `items[].record.container.kind` | `unclassified` | 未分类容器，不携带任何实体 UID。 |
| `items[].record.origin` | `self` | 由当前账号直接形成的记录。 |
| `items[].record.origin` | `topic` | 来源于 Record 个人主题的记录。 |
| `items[].record.origin` | `private_chat` | 来源于私聊的记录。 |
| `items[].record.origin` | `group_chat` | 来源于群聊的记录。 |
| `items[].record.state` | `available` | 记录有效且正文可见，可以读取标题和文本内容。 |
| `items[].record.state` | `protected` | 记录存在但正文受保护，不返回标题和文本内容。 |
| `items[].record.state` | `deleted` | 记录已经软删除，只返回可公开的状态事实。 |
| `items[].record.state` | `hidden` | 记录处于隐藏状态，只返回可公开的状态事实。 |
| `items[].record.state` | `missing` | 当前账号范围内没有可返回的记录事实。 |
| `items[].source.kind` | `record` | 直接命中记录本身，不携带来源 UID。 |
| `items[].source.kind` | `topic` | 通过 Record 个人主题命中，同时返回 topic_uid。 |
| `items[].source.kind` | `chat` | 通过聊天会话命中，同时返回 chat_session_uid。 |
| `refinement_reasons[]` | `keyword_too_short` | 关键词区分度不足；补充更具体的关键词后重新搜索。 |
| `refinement_reasons[]` | `visible_scope_too_large` | 当前可见搜索范围过大；增加日期范围或更具体的关键词后重新搜索。 |
| `refinement_reasons[]` | `candidate_overflow` | 候选数量超过安全处理上限；进一步收窄关键词或日期范围后重新搜索。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "matched_fields": [
          "body"
        ],
        "record": {
          "creator_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
          "origin": "self",
          "record_uid": "record-1",
          "send_at": 1700001000000,
          "state": "available",
          "text_content": "周五下午三点同步进度",
          "title": "项目同步",
          "version": 1
        },
        "snippet": "周五下午三点同步进度",
        "source": {
          "kind": "record"
        }
      }
    ],
    "refinement_required": false
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量读取记录 {#batchGetRecords}

`POST /api/v1/record/records/batch-get`

按输入顺序读取多条记录及其当前可见状态。可用记录同时返回当前主容器和版本。

Operation ID：`batchGetRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `record_uids` | `array<string>` | 是 | 要读取的记录 UID，1 到 10 个。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/record/records/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"record_uids":["record-1"]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入 UID 同序的记录事实；不存在或不可见时通过 state 表达。 |
| `items[].record_uid` | `string` | 是 | 记录 UID；只用于记录查询、更新、移动、删除或安排关联，不能作为聊天会话或个人主题 UID。 |
| `items[].state` | `enum<string>` | 是 | 记录可见性；仅 available 保证返回正文。 |
| `items[].creator_user_ref` | `string` | 否 | 记录创建人的公开用户引用。 |
| `items[].origin` | `enum<string>` | 否 | 记录形成来源。 |
| `items[].title` | `string` | 否 | 记录标题；内容不可见或不存在时省略。 |
| `items[].text_content` | `string` | 否 | 记录纯文本正文；内容不可见或不存在时省略。 |
| `items[].send_at` | `integer` | 否 | 记录业务时间，Unix 毫秒。 |
| `items[].version` | `integer` | 否 | 记录当前版本号，用于防止更新或删除覆盖并发修改。 |
| `items[].container` | `null or object` | 否 | 当前主容器；batch_get 对可用记录保证返回，其他查询可能省略。 |
| `items[].container.kind` | `enum<string>` | 是 | 容器形态；topic 携带 topic_uid，unclassified 不携带实体 UID。 |
| `items[].container.topic_uid` | `string` | 否 | Record 个人主题 UID；仅在 kind 为 topic 时提供，不能传聊天会话 UID。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].container.kind` | `topic` | Record 个人主题容器，必须同时提供 topic_uid。 |
| `items[].container.kind` | `unclassified` | 未分类容器，不携带任何实体 UID。 |
| `items[].origin` | `self` | 由当前账号直接形成的记录。 |
| `items[].origin` | `topic` | 来源于 Record 个人主题的记录。 |
| `items[].origin` | `private_chat` | 来源于私聊的记录。 |
| `items[].origin` | `group_chat` | 来源于群聊的记录。 |
| `items[].state` | `available` | 记录有效且正文可见，可以读取标题和文本内容。 |
| `items[].state` | `protected` | 记录存在但正文受保护，不返回标题和文本内容。 |
| `items[].state` | `deleted` | 记录已经软删除，只返回可公开的状态事实。 |
| `items[].state` | `hidden` | 记录处于隐藏状态，只返回可公开的状态事实。 |
| `items[].state` | `missing` | 当前账号范围内没有可返回的记录事实。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "container": {
          "kind": "topic",
          "topic_uid": "topic-1"
        },
        "creator_user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
        "origin": "self",
        "record_uid": "record-1",
        "send_at": 1700001000000,
        "state": "available",
        "text_content": "周五下午三点同步进度",
        "title": "项目同步",
        "version": 1
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量创建记录 {#createRecords}

`POST /api/v1/record/records/create`

批量创建纯文本记录，可写入已解析的个人主题或未分类容器。每项使用独立幂等键。

Operation ID：`createRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量创建项，1 到 10 项；整批先校验后执行。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].idempotency_key` | `string` | 是 | 调用方生成的稳定幂等键；同一业务创建重试必须复用，最多 128 字符，只能包含字母、数字及 . _ : -。 |
| `items[].title` | `string` | 否 | 记录标题，最多 5000 字；留空允许由正文展示。 |
| `items[].text_content` | `string` | 是 | 记录纯文本正文，1 到 5000 字。 |
| `items[].send_at` | `integer` | 是 | 记录业务时间，Unix 毫秒；重试必须保持不变。 |
| `items[].container` | `null or object` | 否 | 目标容器；留空写入未分类容器。 |
| `items[].container.kind` | `enum<string>` | 是 | 容器形态；topic 携带 topic_uid，unclassified 不携带实体 UID。 |
| `items[].container.topic_uid` | `string` | 否 | Record 个人主题 UID；仅在 kind 为 topic 时提供，不能传聊天会话 UID。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].container.kind` | `topic` | Record 个人主题容器，必须同时提供 topic_uid。 |
| `items[].container.kind` | `unclassified` | 未分类容器，不携带任何实体 UID。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/record/records/create' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"record-1","idempotency_key":"record.project-sync.001","title":"项目同步","text_content":"周五下午三点同步进度","send_at":1700001000000,"container":{"kind":"topic","topic_uid":"topic-1"}}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的创建结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].record_uid` | `string` | 是 | 新建记录的 UID。 |
| `items[].container` | `object` | 是 | 创建完成后记录所在的当前主容器；记录随后被移动时，同一幂等请求重放返回最新主容器。 |
| `items[].container.kind` | `enum<string>` | 是 | 容器形态；topic 携带 topic_uid，unclassified 不携带实体 UID。 |
| `items[].container.topic_uid` | `string` | 否 | Record 个人主题 UID；仅在 kind 为 topic 时提供，不能传聊天会话 UID。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].container.kind` | `topic` | Record 个人主题容器，必须同时提供 topic_uid。 |
| `items[].container.kind` | `unclassified` | 未分类容器，不携带任何实体 UID。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "container": {
          "kind": "topic",
          "topic_uid": "topic-1"
        },
        "item_id": "record-1",
        "record_uid": "record-1"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量更新记录 {#updateRecords}

`POST /api/v1/record/records/update`

使用最近读取到的版本批量更新自己创建的记录标题或正文，防止覆盖并发修改。

Operation ID：`updateRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量更新项，1 到 10 项；各项通过预期版本防止覆盖并发修改。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].idempotency_key` | `string` | 是 | 调用方生成的稳定幂等键；同一更新重试必须复用，最多 128 字符，只能包含字母、数字及 . _ : -。 |
| `items[].record_uid` | `string` | 是 | 要更新的记录 UID。 |
| `items[].expected_version` | `integer` | 是 | 最近一次读取到的版本号；不一致时拒绝更新。 |
| `items[].edit_at` | `integer` | 是 | 编辑时间，Unix 毫秒；重试必须保持不变。 |
| `items[].title` | `null or string` | 否 | 新标题；不传表示保持不变，传空字符串表示清空。 |
| `items[].text_content` | `null or string` | 否 | 新正文；不传表示保持不变，传空字符串表示清空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/record/records/update' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"record-update-1","idempotency_key":"record.update.project-sync.001","record_uid":"record-1","expected_version":1,"edit_at":1700002000000,"text_content":"周五下午四点同步进度"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的更新结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].record_uid` | `string` | 是 | 目标记录 UID。 |
| `items[].status` | `enum<string>` | 是 | 单项处理结果；rejected 表示本次变更未生效。 |
| `items[].reason` | `enum<string>` | 否 | 拒绝代码；成功时省略，冲突类原因应重新读取后再决定。 |
| `items[].version` | `integer` | 否 | 更新后的版本号；仅成功时返回，可用于后续更新或删除。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].reason` | `not_self_created` | 记录不是当前账号创建，公开写能力不允许修改。 |
| `items[].reason` | `protected` | 记录正文受保护，当前操作不允许修改。 |
| `items[].reason` | `not_active` | 记录已不处于可修改的有效状态。 |
| `items[].reason` | `stale_version` | expected_version 已过期；重新读取记录后再决定是否重试。 |
| `items[].reason` | `record_not_found` | 当前账号范围内没有找到目标记录。 |
| `items[].reason` | `revision_conflict` | 当前编辑修订与请求冲突；重新读取并重新形成修改意图。 |
| `items[].reason` | `invalid_record_state` | 记录当前状态不满足该操作的业务合同。 |
| `items[].status` | `succeeded` | 该项操作已经完成，可以使用返回的最新事实。 |
| `items[].status` | `rejected` | 该项操作没有生效；根据 reason 修正输入、重新读取或停止操作。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "item_id": "record-update-1",
        "record_uid": "record-1",
        "status": "succeeded",
        "version": 2
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量移动记录 {#moveRecords}

`POST /api/v1/record/records/move`

使用最近读取到的当前容器，将自己创建的记录批量移动到另一个个人主题或未分类容器。

Operation ID：`moveRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量移动项，1 到 10 项；通过预期容器防止并发覆盖。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].record_uid` | `string` | 是 | 要移动的记录 UID。 |
| `items[].expected_container` | `object` | 是 | 最近一次读取到的当前容器；不一致时拒绝移动。 |
| `items[].expected_container.kind` | `enum<string>` | 是 | 容器形态；topic 携带 topic_uid，unclassified 不携带实体 UID。 |
| `items[].expected_container.topic_uid` | `string` | 否 | Record 个人主题 UID；仅在 kind 为 topic 时提供，不能传聊天会话 UID。 |
| `items[].destination` | `object` | 是 | 要移动到的目标容器。 |
| `items[].destination.kind` | `enum<string>` | 是 | 容器形态；topic 携带 topic_uid，unclassified 不携带实体 UID。 |
| `items[].destination.topic_uid` | `string` | 否 | Record 个人主题 UID；仅在 kind 为 topic 时提供，不能传聊天会话 UID。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].destination.kind` | `topic` | Record 个人主题容器，必须同时提供 topic_uid。 |
| `items[].destination.kind` | `unclassified` | 未分类容器，不携带任何实体 UID。 |
| `items[].expected_container.kind` | `topic` | Record 个人主题容器，必须同时提供 topic_uid。 |
| `items[].expected_container.kind` | `unclassified` | 未分类容器，不携带任何实体 UID。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/record/records/move' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"record-move-1","record_uid":"record-1","expected_container":{"kind":"topic","topic_uid":"topic-1"},"destination":{"kind":"unclassified"}}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的移动结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].record_uid` | `string` | 是 | 目标记录 UID。 |
| `items[].status` | `enum<string>` | 是 | 单项处理结果；rejected 表示本次变更未生效。 |
| `items[].reason` | `enum<string>` | 否 | 拒绝代码；成功时省略，冲突类原因应重新读取后再决定。 |
| `items[].container` | `null or object` | 否 | 成功时记录移动后的当前主容器。 |
| `items[].container.kind` | `enum<string>` | 是 | 容器形态；topic 携带 topic_uid，unclassified 不携带实体 UID。 |
| `items[].container.topic_uid` | `string` | 否 | Record 个人主题 UID；仅在 kind 为 topic 时提供，不能传聊天会话 UID。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].container.kind` | `topic` | Record 个人主题容器，必须同时提供 topic_uid。 |
| `items[].container.kind` | `unclassified` | 未分类容器，不携带任何实体 UID。 |
| `items[].reason` | `not_self_created` | 记录不是当前账号创建，公开写能力不允许修改。 |
| `items[].reason` | `protected` | 记录正文受保护，当前操作不允许修改。 |
| `items[].reason` | `not_active` | 记录已不处于可修改的有效状态。 |
| `items[].reason` | `record_not_found` | 当前账号范围内没有找到目标记录。 |
| `items[].reason` | `destination_unavailable` | 目标容器不存在、不可用或不允许写入。 |
| `items[].reason` | `invalid_record_state` | 记录当前状态不满足该操作的业务合同。 |
| `items[].reason` | `container_changed` | 记录当前容器已不同于 expected_container；重新读取后再决定是否移动。 |
| `items[].status` | `succeeded` | 该项操作已经完成，可以使用返回的最新事实。 |
| `items[].status` | `rejected` | 该项操作没有生效；根据 reason 修正输入、重新读取或停止操作。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "container": {
          "kind": "unclassified"
        },
        "item_id": "record-move-1",
        "record_uid": "record-1",
        "status": "succeeded"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量删除记录 {#deleteRecords}

`POST /api/v1/record/records/delete`

使用最近读取到的版本批量软删除自己创建的记录，防止删除已发生变化的内容。

Operation ID：`deleteRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量删除项，1 到 10 项；通过预期版本防止并发覆盖。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].record_uid` | `string` | 是 | 要删除的记录 UID。 |
| `items[].expected_version` | `integer` | 是 | 最近一次读取到的版本号；不一致时拒绝删除。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/record/records/delete' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"record-delete-1","record_uid":"record-1","expected_version":2}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的删除结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].record_uid` | `string` | 是 | 目标记录 UID。 |
| `items[].status` | `enum<string>` | 是 | 单项处理结果；rejected 表示本次变更未生效。 |
| `items[].reason` | `enum<string>` | 否 | 拒绝代码；成功时省略，冲突类原因应重新读取后再决定。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].reason` | `not_self_created` | 记录不是当前账号创建，公开写能力不允许修改。 |
| `items[].reason` | `protected` | 记录正文受保护，当前操作不允许修改。 |
| `items[].reason` | `not_active` | 记录已不处于可修改的有效状态。 |
| `items[].reason` | `stale_version` | expected_version 已过期；重新读取记录后再决定是否重试。 |
| `items[].reason` | `record_not_found` | 当前账号范围内没有找到目标记录。 |
| `items[].reason` | `invalid_record_state` | 记录当前状态不满足该操作的业务合同。 |
| `items[].status` | `succeeded` | 该项操作已经完成，可以使用返回的最新事实。 |
| `items[].status` | `rejected` | 该项操作没有生效；根据 reason 修正输入、重新读取或停止操作。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "item_id": "record-delete-1",
        "record_uid": "record-1",
        "status": "succeeded"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 安排 {#rest-arrangement}

### 查询安排 {#queryArrangements}

`POST /api/v1/arrangement/query`

按状态、个人主题、关联记录、截止时间或最近更新时间范围分页查询当前账号的未删除安排。

Operation ID：`queryArrangements`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `statuses` | `array<enum<string>>` | 否 | 安排状态筛选；缺省返回全部未删除状态。 |
| `arrangement_uids` | `array<string>` | 否 | 只返回这些安排 UID，最多 10 个；每个 UID 最多 64 字。 |
| `topic_uid` | `string` | 否 | 只返回归属指定 Record 个人主题的安排。 |
| `record_uid` | `string` | 否 | 只返回关联指定记录的安排。 |
| `due_start_at` | `integer` | 否 | 截止时间下界（含），Unix 毫秒；留空不限制。 |
| `due_end_at` | `integer` | 否 | 截止时间上界（含），Unix 毫秒；留空不限制。 |
| `updated_start_at` | `integer` | 否 | 当前安排最近更新时间下界（含），Unix 毫秒；与 statuses 组合时只返回最近更新发生在范围内且当前处于指定状态的安排。 |
| `updated_end_at` | `integer` | 否 | 当前安排最近更新时间上界（含），Unix 毫秒；留空不限制。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明 keyset 游标；首次查询留空，继续时必须保持其他筛选条件不变。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `statuses[]` | `identified` | 已经识别的安排。 |
| `statuses[]` | `following` | 正在跟进的安排。 |
| `statuses[]` | `completed` | 已经完成的安排。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/arrangement/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"statuses":["completed"],"updated_start_at":1700000000000,"updated_end_at":1700086400000,"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 本页安排；未指定截止时间范围时按 updated_at 降序、arrangement_uid 升序排列，指定范围时按 due_at 升序、updated_at 降序、arrangement_uid 升序排列。 |
| `items[].arrangement_uid` | `string` | 是 | 安排 UID；只用于安排查询、更新、状态流转和删除。 |
| `items[].title` | `string` | 否 | 安排标题。 |
| `items[].description` | `string` | 否 | 安排补充说明。 |
| `items[].status` | `enum<string>` | 是 | 安排当前状态。 |
| `items[].topic_uid` | `string` | 否 | 安排归属的 Record 个人主题 UID；不是聊天会话 UID。 |
| `items[].due_at` | `integer` | 否 | 截止时间，Unix 毫秒。 |
| `items[].remind_at` | `integer` | 否 | 计划提醒时间，Unix 毫秒。 |
| `items[].reminder_enabled` | `boolean` | 是 | 是否已启用提醒。 |
| `items[].reminder_state` | `enum<string>` | 否 | 提醒处理状态。 |
| `items[].version` | `integer` | 是 | 安排当前版本号，用于防止更新覆盖并发修改。 |
| `items[].created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].updated_at` | `integer` | 是 | 最近更新时间，Unix 毫秒。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明 keyset 游标；has_more 为 true 时原样传回 page_cursor。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].reminder_state` | `pending` | 提醒已经排定，等待触发。 |
| `items[].reminder_state` | `delivered` | 提醒已经投递。 |
| `items[].reminder_state` | `cancelled` | 原提醒计划已经取消。 |
| `items[].reminder_state` | `disabled` | 当前安排未启用提醒。 |
| `items[].status` | `identified` | 已经识别的安排。 |
| `items[].status` | `following` | 正在跟进的安排。 |
| `items[].status` | `completed` | 已经完成的安排。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "arrangement_uid": "arrangement-1",
        "created_at": 1700000000000,
        "description": "准备本周进度",
        "due_at": 1700086400000,
        "reminder_enabled": false,
        "reminder_state": "disabled",
        "status": "completed",
        "title": "项目同步",
        "topic_uid": "topic-1",
        "updated_at": 1700000000000,
        "version": 1
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量读取安排 {#batchGetArrangements}

`POST /api/v1/arrangement/batch-get`

按输入顺序读取多条安排，并明确返回每个 UID 是否存在以及当前完整事实。

Operation ID：`batchGetArrangements`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `arrangement_uids` | `array<string>` | 是 | 要读取的安排 UID，1 到 10 个；每个 UID 最多 64 字；结果与输入同序。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/arrangement/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"arrangement_uids":["arrangement-1"]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入 UID 同序的读取结果。 |
| `items[].arrangement_uid` | `string` | 是 | 输入的安排 UID。 |
| `items[].found` | `boolean` | 是 | 是否找到当前账号可见的安排。 |
| `items[].arrangement` | `null or object` | 否 | found 为 true 时的完整安排事实。 |
| `items[].arrangement.arrangement_uid` | `string` | 是 | 安排 UID；只用于安排查询、更新、状态流转和删除。 |
| `items[].arrangement.title` | `string` | 否 | 安排标题。 |
| `items[].arrangement.description` | `string` | 否 | 安排补充说明。 |
| `items[].arrangement.status` | `enum<string>` | 是 | 安排当前状态；deleted 表示已软删除。 |
| `items[].arrangement.topic_uid` | `string` | 否 | 安排归属的 Record 个人主题 UID；不是聊天会话 UID。 |
| `items[].arrangement.due_at` | `integer` | 否 | 截止时间，Unix 毫秒。 |
| `items[].arrangement.remind_at` | `integer` | 否 | 计划提醒时间，Unix 毫秒。 |
| `items[].arrangement.reminder_enabled` | `boolean` | 是 | 是否已启用提醒。 |
| `items[].arrangement.reminder_state` | `enum<string>` | 否 | 提醒处理状态。 |
| `items[].arrangement.version` | `integer` | 是 | 安排当前版本号，用于防止更新覆盖并发修改。 |
| `items[].arrangement.created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].arrangement.updated_at` | `integer` | 是 | 最近更新时间，Unix 毫秒。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].arrangement.reminder_state` | `pending` | 提醒已经排定，等待触发。 |
| `items[].arrangement.reminder_state` | `delivered` | 提醒已经投递。 |
| `items[].arrangement.reminder_state` | `cancelled` | 原提醒计划已经取消。 |
| `items[].arrangement.reminder_state` | `disabled` | 当前安排未启用提醒。 |
| `items[].arrangement.status` | `identified` | 已经识别的安排。 |
| `items[].arrangement.status` | `following` | 正在跟进的安排。 |
| `items[].arrangement.status` | `completed` | 已经完成的安排。 |
| `items[].arrangement.status` | `deleted` | 已经软删除的安排；只在相关读取或写入结果中出现。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "arrangement": {
          "arrangement_uid": "arrangement-1",
          "created_at": 1700000000000,
          "description": "准备本周进度",
          "due_at": 1700086400000,
          "reminder_enabled": false,
          "reminder_state": "disabled",
          "status": "following",
          "title": "项目同步",
          "topic_uid": "topic-1",
          "updated_at": 1700000000000,
          "version": 1
        },
        "arrangement_uid": "arrangement-1",
        "found": true
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量创建安排 {#createArrangements}

`POST /api/v1/arrangement/create`

批量创建安排，可关联已解析的个人主题和可选截止时间。每项使用独立幂等键。

Operation ID：`createArrangements`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量创建项，1 到 10 项；整批先校验后执行。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].idempotency_key` | `string` | 是 | 调用方生成的稳定幂等键；同一创建重试必须复用，最多 128 字符，只能包含字母、数字及 . _ : -。 |
| `items[].title` | `string` | 是 | 安排标题，1 到 200 字。 |
| `items[].description` | `string` | 否 | 安排补充说明，最多 5000 字。 |
| `items[].topic_uid` | `string` | 否 | 可选归属 Record 个人主题 UID；必须使用 list_record_containers 或 resolve_record_containers 返回的 topic_uid，不能传 chat_session_uid。 |
| `items[].due_at` | `integer` | 否 | 可选截止时间，Unix 毫秒。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/arrangement/create' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"arrangement-1","idempotency_key":"arrangement.project-sync.001","title":"项目同步","description":"准备本周进度","topic_uid":"topic-1","due_at":1700086400000}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的创建结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].status` | `enum<string>` | 是 | 单项写入结果；rejected 表示本次变更未生效。 |
| `items[].reason` | `enum<string>` | 否 | 拒绝代码；成功时省略，变更冲突应重新读取后再决定。 |
| `items[].arrangement` | `null or object` | 否 | 处理成功后的完整安排事实。 |
| `items[].arrangement.arrangement_uid` | `string` | 是 | 安排 UID；只用于安排查询、更新、状态流转和删除。 |
| `items[].arrangement.title` | `string` | 否 | 安排标题。 |
| `items[].arrangement.description` | `string` | 否 | 安排补充说明。 |
| `items[].arrangement.status` | `enum<string>` | 是 | 安排当前状态；deleted 表示已软删除。 |
| `items[].arrangement.topic_uid` | `string` | 否 | 安排归属的 Record 个人主题 UID；不是聊天会话 UID。 |
| `items[].arrangement.due_at` | `integer` | 否 | 截止时间，Unix 毫秒。 |
| `items[].arrangement.remind_at` | `integer` | 否 | 计划提醒时间，Unix 毫秒。 |
| `items[].arrangement.reminder_enabled` | `boolean` | 是 | 是否已启用提醒。 |
| `items[].arrangement.reminder_state` | `enum<string>` | 否 | 提醒处理状态。 |
| `items[].arrangement.version` | `integer` | 是 | 安排当前版本号，用于防止更新覆盖并发修改。 |
| `items[].arrangement.created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].arrangement.updated_at` | `integer` | 是 | 最近更新时间，Unix 毫秒。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].arrangement.reminder_state` | `pending` | 提醒已经排定，等待触发。 |
| `items[].arrangement.reminder_state` | `delivered` | 提醒已经投递。 |
| `items[].arrangement.reminder_state` | `cancelled` | 原提醒计划已经取消。 |
| `items[].arrangement.reminder_state` | `disabled` | 当前安排未启用提醒。 |
| `items[].arrangement.status` | `identified` | 已经识别的安排。 |
| `items[].arrangement.status` | `following` | 正在跟进的安排。 |
| `items[].arrangement.status` | `completed` | 已经完成的安排。 |
| `items[].arrangement.status` | `deleted` | 已经软删除的安排；只在相关读取或写入结果中出现。 |
| `items[].reason` | `not_found` | 当前账号范围内没有找到目标安排。 |
| `items[].reason` | `state_changed` | 安排状态已不同于 expected_status；重新读取后再决定。 |
| `items[].reason` | `version_changed` | 安排版本已不同于 expected_version；重新读取后再决定。 |
| `items[].status` | `succeeded` | 该项操作已经完成，可以使用返回的最新安排事实。 |
| `items[].status` | `rejected` | 该项操作没有生效；根据 reason 重新读取或修正请求。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "arrangement": {
          "arrangement_uid": "arrangement-1",
          "created_at": 1700000000000,
          "description": "准备本周进度",
          "due_at": 1700086400000,
          "reminder_enabled": false,
          "reminder_state": "disabled",
          "status": "identified",
          "title": "项目同步",
          "topic_uid": "topic-1",
          "updated_at": 1700000000000,
          "version": 1
        },
        "item_id": "arrangement-1",
        "status": "succeeded"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量更新安排 {#updateArrangements}

`POST /api/v1/arrangement/update`

使用最近读取到的版本批量修改安排标题、说明或截止时间，并返回当前完整安排。

Operation ID：`updateArrangements`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量更新项，1 到 10 项；按目标最终状态收敛。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].arrangement_uid` | `string` | 是 | 要更新的安排 UID，最多 64 字。 |
| `items[].expected_version` | `integer` | 是 | 最近一次读取到的版本号；不一致且目标字段尚未生效时拒绝更新。 |
| `items[].title` | `null or string` | 否 | 新标题；不传表示保持不变。 |
| `items[].description` | `null or string` | 否 | 新说明；不传表示保持不变，传空字符串表示清空。 |
| `items[].due_at` | `null or integer` | 否 | 新截止时间（Unix 毫秒）；不传保持不变，传 0 表示清除。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/arrangement/update' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"arrangement-update-1","arrangement_uid":"arrangement-1","expected_version":1,"title":"项目周会"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的更新结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].status` | `enum<string>` | 是 | 单项写入结果；rejected 表示本次变更未生效。 |
| `items[].reason` | `enum<string>` | 否 | 拒绝代码；成功时省略，变更冲突应重新读取后再决定。 |
| `items[].arrangement` | `null or object` | 否 | 处理成功后的完整安排事实。 |
| `items[].arrangement.arrangement_uid` | `string` | 是 | 安排 UID；只用于安排查询、更新、状态流转和删除。 |
| `items[].arrangement.title` | `string` | 否 | 安排标题。 |
| `items[].arrangement.description` | `string` | 否 | 安排补充说明。 |
| `items[].arrangement.status` | `enum<string>` | 是 | 安排当前状态；deleted 表示已软删除。 |
| `items[].arrangement.topic_uid` | `string` | 否 | 安排归属的 Record 个人主题 UID；不是聊天会话 UID。 |
| `items[].arrangement.due_at` | `integer` | 否 | 截止时间，Unix 毫秒。 |
| `items[].arrangement.remind_at` | `integer` | 否 | 计划提醒时间，Unix 毫秒。 |
| `items[].arrangement.reminder_enabled` | `boolean` | 是 | 是否已启用提醒。 |
| `items[].arrangement.reminder_state` | `enum<string>` | 否 | 提醒处理状态。 |
| `items[].arrangement.version` | `integer` | 是 | 安排当前版本号，用于防止更新覆盖并发修改。 |
| `items[].arrangement.created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].arrangement.updated_at` | `integer` | 是 | 最近更新时间，Unix 毫秒。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].arrangement.reminder_state` | `pending` | 提醒已经排定，等待触发。 |
| `items[].arrangement.reminder_state` | `delivered` | 提醒已经投递。 |
| `items[].arrangement.reminder_state` | `cancelled` | 原提醒计划已经取消。 |
| `items[].arrangement.reminder_state` | `disabled` | 当前安排未启用提醒。 |
| `items[].arrangement.status` | `identified` | 已经识别的安排。 |
| `items[].arrangement.status` | `following` | 正在跟进的安排。 |
| `items[].arrangement.status` | `completed` | 已经完成的安排。 |
| `items[].arrangement.status` | `deleted` | 已经软删除的安排；只在相关读取或写入结果中出现。 |
| `items[].reason` | `not_found` | 当前账号范围内没有找到目标安排。 |
| `items[].reason` | `state_changed` | 安排状态已不同于 expected_status；重新读取后再决定。 |
| `items[].reason` | `version_changed` | 安排版本已不同于 expected_version；重新读取后再决定。 |
| `items[].status` | `succeeded` | 该项操作已经完成，可以使用返回的最新安排事实。 |
| `items[].status` | `rejected` | 该项操作没有生效；根据 reason 重新读取或修正请求。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "arrangement": {
          "arrangement_uid": "arrangement-1",
          "created_at": 1700000000000,
          "description": "准备本周进度",
          "due_at": 1700086400000,
          "reminder_enabled": false,
          "reminder_state": "disabled",
          "status": "identified",
          "title": "项目周会",
          "topic_uid": "topic-1",
          "updated_at": 1700002000000,
          "version": 2
        },
        "item_id": "arrangement-update-1",
        "status": "succeeded"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量流转安排状态 {#transitionArrangements}

`POST /api/v1/arrangement/transition`

使用最近读取到的状态，将安排批量流转到允许的目标状态，并返回当前完整安排。

Operation ID：`transitionArrangements`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量状态流转项，1 到 10 项；通过预期状态防止并发覆盖。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].arrangement_uid` | `string` | 是 | 要流转的安排 UID，最多 64 字。 |
| `items[].expected_status` | `enum<string>` | 是 | 最近读取的安排状态，用于并发校验。 |
| `items[].target_status` | `enum<string>` | 是 | 目标状态；只接受 Schema 声明的状态流转组合。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].expected_status` | `identified` | 最近读取到的状态是 identified；服务端状态不一致时拒绝本项操作。 |
| `items[].expected_status` | `following` | 最近读取到的状态是 following；服务端状态不一致时拒绝本项操作。 |
| `items[].expected_status` | `completed` | 最近读取到的状态是 completed；服务端状态不一致时拒绝本项操作。 |
| `items[].target_status` | `identified` | 将 following 安排恢复为 identified。 |
| `items[].target_status` | `following` | 将 identified 安排开始跟进，或将 completed 安排恢复为 following。 |
| `items[].target_status` | `completed` | 将 following 安排标记为 completed。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/arrangement/transition' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"arrangement-transition-1","arrangement_uid":"arrangement-1","expected_status":"identified","target_status":"following"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的状态流转结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].status` | `enum<string>` | 是 | 单项写入结果；rejected 表示本次变更未生效。 |
| `items[].reason` | `enum<string>` | 否 | 拒绝代码；成功时省略，变更冲突应重新读取后再决定。 |
| `items[].arrangement` | `null or object` | 否 | 处理成功后的完整安排事实。 |
| `items[].arrangement.arrangement_uid` | `string` | 是 | 安排 UID；只用于安排查询、更新、状态流转和删除。 |
| `items[].arrangement.title` | `string` | 否 | 安排标题。 |
| `items[].arrangement.description` | `string` | 否 | 安排补充说明。 |
| `items[].arrangement.status` | `enum<string>` | 是 | 安排当前状态；deleted 表示已软删除。 |
| `items[].arrangement.topic_uid` | `string` | 否 | 安排归属的 Record 个人主题 UID；不是聊天会话 UID。 |
| `items[].arrangement.due_at` | `integer` | 否 | 截止时间，Unix 毫秒。 |
| `items[].arrangement.remind_at` | `integer` | 否 | 计划提醒时间，Unix 毫秒。 |
| `items[].arrangement.reminder_enabled` | `boolean` | 是 | 是否已启用提醒。 |
| `items[].arrangement.reminder_state` | `enum<string>` | 否 | 提醒处理状态。 |
| `items[].arrangement.version` | `integer` | 是 | 安排当前版本号，用于防止更新覆盖并发修改。 |
| `items[].arrangement.created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].arrangement.updated_at` | `integer` | 是 | 最近更新时间，Unix 毫秒。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].arrangement.reminder_state` | `pending` | 提醒已经排定，等待触发。 |
| `items[].arrangement.reminder_state` | `delivered` | 提醒已经投递。 |
| `items[].arrangement.reminder_state` | `cancelled` | 原提醒计划已经取消。 |
| `items[].arrangement.reminder_state` | `disabled` | 当前安排未启用提醒。 |
| `items[].arrangement.status` | `identified` | 已经识别的安排。 |
| `items[].arrangement.status` | `following` | 正在跟进的安排。 |
| `items[].arrangement.status` | `completed` | 已经完成的安排。 |
| `items[].arrangement.status` | `deleted` | 已经软删除的安排；只在相关读取或写入结果中出现。 |
| `items[].reason` | `not_found` | 当前账号范围内没有找到目标安排。 |
| `items[].reason` | `state_changed` | 安排状态已不同于 expected_status；重新读取后再决定。 |
| `items[].reason` | `version_changed` | 安排版本已不同于 expected_version；重新读取后再决定。 |
| `items[].status` | `succeeded` | 该项操作已经完成，可以使用返回的最新安排事实。 |
| `items[].status` | `rejected` | 该项操作没有生效；根据 reason 重新读取或修正请求。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "arrangement": {
          "arrangement_uid": "arrangement-1",
          "created_at": 1700000000000,
          "description": "准备本周进度",
          "due_at": 1700086400000,
          "reminder_enabled": false,
          "reminder_state": "disabled",
          "status": "following",
          "title": "项目同步",
          "topic_uid": "topic-1",
          "updated_at": 1700002000000,
          "version": 2
        },
        "item_id": "arrangement-transition-1",
        "status": "succeeded"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 批量删除安排 {#deleteArrangements}

`POST /api/v1/arrangement/delete`

使用最近读取到的状态批量软删除安排，并返回删除后的完整安排事实。

Operation ID：`deleteArrangements`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量删除项，1 到 10 项；通过预期状态防止并发覆盖。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].arrangement_uid` | `string` | 是 | 要删除的安排 UID，最多 64 字。 |
| `items[].expected_status` | `enum<string>` | 是 | 最近读取的安排状态，用于并发校验。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].expected_status` | `identified` | 最近读取到的状态是 identified；服务端状态不一致时拒绝本项操作。 |
| `items[].expected_status` | `following` | 最近读取到的状态是 following；服务端状态不一致时拒绝本项操作。 |
| `items[].expected_status` | `completed` | 最近读取到的状态是 completed；服务端状态不一致时拒绝本项操作。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/arrangement/delete' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"arrangement-delete-1","arrangement_uid":"arrangement-1","expected_status":"following"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的删除结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].status` | `enum<string>` | 是 | 单项写入结果；rejected 表示本次变更未生效。 |
| `items[].reason` | `enum<string>` | 否 | 拒绝代码；成功时省略，变更冲突应重新读取后再决定。 |
| `items[].arrangement` | `null or object` | 否 | 处理成功后的完整安排事实。 |
| `items[].arrangement.arrangement_uid` | `string` | 是 | 安排 UID；只用于安排查询、更新、状态流转和删除。 |
| `items[].arrangement.title` | `string` | 否 | 安排标题。 |
| `items[].arrangement.description` | `string` | 否 | 安排补充说明。 |
| `items[].arrangement.status` | `enum<string>` | 是 | 安排当前状态；deleted 表示已软删除。 |
| `items[].arrangement.topic_uid` | `string` | 否 | 安排归属的 Record 个人主题 UID；不是聊天会话 UID。 |
| `items[].arrangement.due_at` | `integer` | 否 | 截止时间，Unix 毫秒。 |
| `items[].arrangement.remind_at` | `integer` | 否 | 计划提醒时间，Unix 毫秒。 |
| `items[].arrangement.reminder_enabled` | `boolean` | 是 | 是否已启用提醒。 |
| `items[].arrangement.reminder_state` | `enum<string>` | 否 | 提醒处理状态。 |
| `items[].arrangement.version` | `integer` | 是 | 安排当前版本号，用于防止更新覆盖并发修改。 |
| `items[].arrangement.created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].arrangement.updated_at` | `integer` | 是 | 最近更新时间，Unix 毫秒。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].arrangement.reminder_state` | `pending` | 提醒已经排定，等待触发。 |
| `items[].arrangement.reminder_state` | `delivered` | 提醒已经投递。 |
| `items[].arrangement.reminder_state` | `cancelled` | 原提醒计划已经取消。 |
| `items[].arrangement.reminder_state` | `disabled` | 当前安排未启用提醒。 |
| `items[].arrangement.status` | `identified` | 已经识别的安排。 |
| `items[].arrangement.status` | `following` | 正在跟进的安排。 |
| `items[].arrangement.status` | `completed` | 已经完成的安排。 |
| `items[].arrangement.status` | `deleted` | 已经软删除的安排；只在相关读取或写入结果中出现。 |
| `items[].reason` | `not_found` | 当前账号范围内没有找到目标安排。 |
| `items[].reason` | `state_changed` | 安排状态已不同于 expected_status；重新读取后再决定。 |
| `items[].reason` | `version_changed` | 安排版本已不同于 expected_version；重新读取后再决定。 |
| `items[].status` | `succeeded` | 该项操作已经完成，可以使用返回的最新安排事实。 |
| `items[].status` | `rejected` | 该项操作没有生效；根据 reason 重新读取或修正请求。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "arrangement": {
          "arrangement_uid": "arrangement-1",
          "created_at": 1700000000000,
          "description": "准备本周进度",
          "due_at": 1700086400000,
          "reminder_enabled": false,
          "reminder_state": "cancelled",
          "status": "deleted",
          "title": "项目同步",
          "topic_uid": "topic-1",
          "updated_at": 1700002000000,
          "version": 2
        },
        "item_id": "arrangement-delete-1",
        "status": "succeeded"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 团队 {#rest-team}

### 移除团队成员 {#removeTeamMembers}

`POST /api/v1/teams/members/remove`

仅团队所有者可批量移除其他成员，不能移除所有者；成功包含目标已非有效成员的空操作，不禁止重新加入。依赖故障可能已有部分项执行；相同目标可重试，但重新加入后的再次移除会作用于当前成员关系。

Operation ID：`removeTeamMembers`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 团队成员移除项，1 到 10 项；item_id 和团队与目标用户组合在本批内不能重复。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].team_ref` | `string` | 是 | 当前账号团队列表或解析结果中的团队引用；调用账号必须是团队所有者。 |
| `items[].target_user_ref` | `string` | 是 | 待移除用户的引用，通常来自该团队成员列表的 user_ref；不能使用昵称或群会话标识，不能移除团队所有者。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/teams/members/remove' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"team-remove-1","team_ref":"team_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","target_user_ref":"usr_v1_BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的逐项移除结果；批次不提供整体事务，依赖故障时可能已有部分项执行。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].status` | `enum<string>` | 是 | 逐项团队成员移除结果。 |
| `items[].reason` | `enum<string>` | 否 | 统一拒绝原因，不披露不可见团队是否存在。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].reason` | `removal_not_allowed` | 团队不可用、调用账号不是团队所有者，或目标为团队所有者。 |
| `items[].status` | `succeeded` | 移除成功，包含目标已非有效成员的空操作。 |
| `items[].status` | `rejected` | 当前团队状态或权限不允许移除。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "item_id": "team-remove-1",
        "status": "succeeded"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 列出我的团队 {#listMyTeams}

`POST /api/v1/teams/list`

稳定分页列出当前账号拥有或加入的有效团队。

Operation ID：`listMyTeams`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 100；缺省为 50。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/teams/list' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"limit":50}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 当前账号拥有或加入的有效团队，按成员关系时间倒序稳定排列。 |
| `items[].team_ref` | `string` | 是 | 当前调用账号范围内稳定的团队引用，只可用于 team_ref 语义字段。 |
| `items[].name` | `string` | 是 | 团队显示名称；不承担唯一身份语义。 |
| `items[].jotmo_id` | `string` | 是 | 团队当前即我号；按即我号加入时使用该精确值。 |
| `items[].current_user_role` | `enum<string>` | 是 | 由 Team owner 确认的当前有效团队角色。 |
| `items[].created_at` | `integer` | 是 | 团队创建时间，Unix 毫秒。 |
| `items[].updated_at` | `integer` | 是 | 团队资料最近更新时间，Unix 毫秒。 |
| `total_count` | `integer` | 是 | 当前账号拥有或加入的有效团队总数。 |
| `has_more` | `boolean` | 是 | 是否还有下一页团队。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].current_user_role` | `owner` | 当前账号或成员是团队拥有者。 |
| `items[].current_user_role` | `admin` | 成员是团队管理员。 |
| `items[].current_user_role` | `member` | 成员是普通团队成员。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "created_at": 1700000000000,
        "current_user_role": "owner",
        "jotmo_id": "research_team",
        "name": "研发团队",
        "team_ref": "team_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
        "updated_at": 1700000000000
      }
    ],
    "total_count": 1
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 解析我的团队 {#resolveMyTeams}

`POST /api/v1/teams/resolve`

只在当前账号的有效团队内按精确即我号或精确名称解析候选。

Operation ID：`resolveMyTeams`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量团队解析项，1 到 10 项；单项调用也传一个元素。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].query` | `string` | 是 | 精确团队即我号或精确团队名称，最多 100 字。 |
| `items[].limit` | `integer` | 否 | 本页候选上限，1 到 10；缺省为 5。 |
| `items[].page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次解析留空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/teams/resolve' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"team-1","query":"研发团队","limit":5}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的团队解析结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].candidates` | `array<object>` | 是 | 当前账号有效团队中的精确匹配候选；重名时保留多个候选。 |
| `items[].candidates[].team_ref` | `string` | 是 | 当前调用账号范围内稳定的团队引用，只可用于 team_ref 语义字段。 |
| `items[].candidates[].name` | `string` | 是 | 团队显示名称；不承担唯一身份语义。 |
| `items[].candidates[].jotmo_id` | `string` | 是 | 团队当前即我号；按即我号加入时使用该精确值。 |
| `items[].candidates[].current_user_role` | `enum<string>` | 是 | 由 Team owner 确认的当前有效团队角色。 |
| `items[].candidates[].created_at` | `integer` | 是 | 团队创建时间，Unix 毫秒。 |
| `items[].candidates[].updated_at` | `integer` | 是 | 团队资料最近更新时间，Unix 毫秒。 |
| `items[].has_more` | `boolean` | 是 | 是否还有下一页候选。 |
| `items[].next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].candidates[].current_user_role` | `owner` | 当前账号或成员是团队拥有者。 |
| `items[].candidates[].current_user_role` | `admin` | 成员是团队管理员。 |
| `items[].candidates[].current_user_role` | `member` | 成员是普通团队成员。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "candidates": [
          {
            "created_at": 1700000000000,
            "current_user_role": "owner",
            "jotmo_id": "research_team",
            "name": "研发团队",
            "team_ref": "team_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            "updated_at": 1700000000000
          }
        ],
        "has_more": false,
        "item_id": "team-1"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 列出团队成员 {#listTeamMembers}

`POST /api/v1/teams/members/list`

使用 team_ref 稳定分页读取当前账号有权访问的团队成员。

Operation ID：`listTeamMembers`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `team_ref` | `string` | 是 | 要读取成员的团队引用，必须来自当前账号的团队列表或解析结果。 |
| `limit` | `integer` | 否 | 本页最多返回条数，1 到 50；缺省为 50。 |
| `page_cursor` | `string` | 否 | 上一页返回的不透明游标；首次查询留空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/teams/members/list' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"team_ref":"team_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","limit":50}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `team` | `object` | 是 | 经 Team owner 确认且当前账号仍有访问权的团队事实。 |
| `team.team_ref` | `string` | 是 | 当前调用账号范围内稳定的团队引用，只可用于 team_ref 语义字段。 |
| `team.name` | `string` | 是 | 团队显示名称；不承担唯一身份语义。 |
| `team.jotmo_id` | `string` | 是 | 团队当前即我号；按即我号加入时使用该精确值。 |
| `team.current_user_role` | `enum<string>` | 是 | 由 Team owner 确认的当前有效团队角色。 |
| `team.created_at` | `integer` | 是 | 团队创建时间，Unix 毫秒。 |
| `team.updated_at` | `integer` | 是 | 团队资料最近更新时间，Unix 毫秒。 |
| `items` | `array<object>` | 是 | 本页有效成员；owner 固定在第一页首项，其余成员按加入时间正序排列。 |
| `items[].user_ref` | `string` | 是 | 成员的公开用户引用；与 team_ref 不可互换。 |
| `items[].display_name` | `string` | 是 | Backend 当前提供的公开显示名；只用于展示。 |
| `items[].jotmo_id` | `string` | 否 | Backend 当前提供的用户即我号；资料不可用时省略。 |
| `items[].identity_state` | `enum<string>` | 是 | Backend 公开身份资料的可用程度。 |
| `items[].role` | `enum<string>` | 是 | 由 Team owner 确认的当前有效团队角色。 |
| `items[].joined_at` | `integer` | 是 | 成员加入时间；owner 使用团队创建时间，Unix 毫秒。 |
| `total_count` | `integer` | 是 | 团队当前有效成员总数，包含 owner。 |
| `has_more` | `boolean` | 是 | 是否还有下一页成员。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标；has_more 为 true 时原样传回。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].identity_state` | `ready` | 用户公开身份资料完整可用。 |
| `items[].identity_state` | `incomplete` | 用户存在，但部分公开展示资料尚未就绪。 |
| `items[].identity_state` | `unavailable` | 本项没有可用的公开身份资料，成员关系仍有效。 |
| `items[].role` | `owner` | 当前账号或成员是团队拥有者。 |
| `items[].role` | `admin` | 成员是团队管理员。 |
| `items[].role` | `member` | 成员是普通团队成员。 |
| `team.current_user_role` | `owner` | 当前账号或成员是团队拥有者。 |
| `team.current_user_role` | `admin` | 成员是团队管理员。 |
| `team.current_user_role` | `member` | 成员是普通团队成员。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": [
      {
        "display_name": "小明",
        "identity_state": "ready",
        "joined_at": 1700000000000,
        "jotmo_id": "xiaoming",
        "role": "owner",
        "user_ref": "usr_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
      }
    ],
    "team": {
      "created_at": 1700000000000,
      "current_user_role": "owner",
      "jotmo_id": "research_team",
      "name": "研发团队",
      "team_ref": "team_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
      "updated_at": 1700000000000
    },
    "total_count": 1
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 创建团队 {#createTeams}

`POST /api/v1/teams/create`

批量创建普通团队；每项使用独立幂等键并返回 Team owner 的确定性结果。

Operation ID：`createTeams`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量团队创建项，1 到 10 项；每项独立返回确定性结果。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].idempotency_key` | `string` | 是 | 调用方生成的稳定幂等键；同一创建重试必须复用，最多 128 字符。 |
| `items[].name` | `string` | 是 | 团队显示名称，1 到 64 字。 |
| `items[].jotmo_id` | `string` | 是 | 要申请的团队即我号，6 到 32 个字符，以字母开头且仅含字母、数字、下划线、连字符。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/teams/create' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"team-create-1","idempotency_key":"team.create.research.001","name":"研发团队","jotmo_id":"research_team"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的团队创建结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].status` | `enum<string>` | 是 | 单项 Team 治理结果。 |
| `items[].reason` | `enum<string>` | 否 | 确定性拒绝代码；成功时省略。 |
| `items[].team` | `null or object` | 否 | 成功时由 Team owner 返回的当前团队事实。 |
| `items[].team.team_ref` | `string` | 是 | 当前调用账号范围内稳定的团队引用，只可用于 team_ref 语义字段。 |
| `items[].team.name` | `string` | 是 | 团队显示名称；不承担唯一身份语义。 |
| `items[].team.jotmo_id` | `string` | 是 | 团队当前即我号；按即我号加入时使用该精确值。 |
| `items[].team.current_user_role` | `enum<string>` | 是 | 由 Team owner 确认的当前有效团队角色。 |
| `items[].team.created_at` | `integer` | 是 | 团队创建时间，Unix 毫秒。 |
| `items[].team.updated_at` | `integer` | 是 | 团队资料最近更新时间，Unix 毫秒。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].reason` | `jotmo_id_unavailable` | 团队即我号已被命名域占用。 |
| `items[].reason` | `idempotency_conflict` | 相同幂等键已绑定不同创建语义。 |
| `items[].status` | `succeeded` | Team owner 已确认本项成功收敛。 |
| `items[].status` | `rejected` | 本项因确定性业务条件未执行成功。 |
| `items[].team.current_user_role` | `owner` | 当前账号或成员是团队拥有者。 |
| `items[].team.current_user_role` | `admin` | 成员是团队管理员。 |
| `items[].team.current_user_role` | `member` | 成员是普通团队成员。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "item_id": "team-create-1",
        "status": "succeeded",
        "team": {
          "created_at": 1700000000000,
          "current_user_role": "owner",
          "jotmo_id": "research_team",
          "name": "研发团队",
          "team_ref": "team_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
          "updated_at": 1700000000000
        }
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 按即我号加入团队 {#joinTeamsByPublicID}

`POST /api/v1/teams/join-by-jotmo-id`

批量按精确团队即我号幂等确认当前账号的 owner 或成员关系。

Operation ID：`joinTeamsByPublicID`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 批量按团队即我号加入项，1 到 10 项；每项独立返回确定性结果。 |
| `items[].item_id` | `string` | 是 | 调用方在本批次内唯一的关联标识，UTF-8 编码最多 64 字节。 |
| `items[].jotmo_id` | `string` | 是 | 要加入团队的精确即我号；不能使用团队名称或 team_ref。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/teams/join-by-jotmo-id' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"team-join-1","jotmo_id":"research_team"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的团队加入结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项的 item_id。 |
| `items[].status` | `enum<string>` | 是 | 单项 Team 治理结果。 |
| `items[].reason` | `enum<string>` | 否 | 确定性拒绝代码；成功时省略。 |
| `items[].membership_state` | `enum<string>` | 否 | 加入成功后的关系收敛结果。 |
| `items[].team` | `null or object` | 否 | 成功时由 Team owner 返回的当前团队事实。 |
| `items[].team.team_ref` | `string` | 是 | 当前调用账号范围内稳定的团队引用，只可用于 team_ref 语义字段。 |
| `items[].team.name` | `string` | 是 | 团队显示名称；不承担唯一身份语义。 |
| `items[].team.jotmo_id` | `string` | 是 | 团队当前即我号；按即我号加入时使用该精确值。 |
| `items[].team.current_user_role` | `enum<string>` | 是 | 由 Team owner 确认的当前有效团队角色。 |
| `items[].team.created_at` | `integer` | 是 | 团队创建时间，Unix 毫秒。 |
| `items[].team.updated_at` | `integer` | 是 | 团队资料最近更新时间，Unix 毫秒。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].membership_state` | `joined` | 本次调用激活了成员关系。 |
| `items[].membership_state` | `already_member` | 调用前已是有效成员，本次为幂等确认。 |
| `items[].membership_state` | `owner` | 当前账号本来就是团队 owner。 |
| `items[].reason` | `team_not_found` | 没有找到该精确即我号对应的有效团队。 |
| `items[].status` | `succeeded` | Team owner 已确认本项成功收敛。 |
| `items[].status` | `rejected` | 本项因确定性业务条件未执行成功。 |
| `items[].team.current_user_role` | `owner` | 当前账号或成员是团队拥有者。 |
| `items[].team.current_user_role` | `admin` | 成员是团队管理员。 |
| `items[].team.current_user_role` | `member` | 成员是普通团队成员。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "item_id": "team-join-1",
        "membership_state": "joined",
        "status": "succeeded",
        "team": {
          "created_at": 1700000000000,
          "current_user_role": "member",
          "jotmo_id": "research_team",
          "name": "研发团队",
          "team_ref": "team_v1_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
          "updated_at": 1700000000000
        }
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 世界 {#rest-world}

### 查询世界动态 {#queryWorldRecords}

`POST /api/v1/world/records/query`

按公开、本人或指定作者范围分页读取当前快照摘要；text_truncated 为 true 时用详情工具读取完整正文。不标记已读、不生成内容。

Operation ID：`queryWorldRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `scope` | `enum<string>` | 否 | 查询范围；缺省 public。 |
| `author_user_ref` | `string` | 否 | 作者的公开用户引用；仅 scope=author 时必填。 |
| `record_type` | `enum<string>` | 否 | 可选世界动态类型。 |
| `tags` | `array<string>` | 否 | 同时包含的标签，最多 20 个，每个最多 100 字节。 |
| `start_at` | `integer` | 否 | 公开时间起点（含），Unix 毫秒。 |
| `end_at` | `integer` | 否 | 公开时间终点（含），Unix 毫秒。 |
| `limit` | `integer` | 否 | 每页条数，1 到 100，缺省 20。 |
| `page_cursor` | `string` | 否 | 上一页的不透明游标；续页保持筛选条件不变。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `record_type` | `record` | 普通源快记的世界发布快照。 |
| `record_type` | `extension_publication` | 插件发布事件的世界展示快照，不是可编辑快记。 |
| `scope` | `public` | 所有人当前公开且通过审核的动态。 |
| `scope` | `mine` | 本人当前发布事实，包括待审及已撤回快照。 |
| `scope` | `author` | 指定作者当前公开且通过审核的动态。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/world/records/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"scope":"public","limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 当前可见的世界动态；分页反映实时事实，不保证跨页快照隔离。 |
| `items[].record_uid` | `string` | 是 | 世界快照对应的源快记 UID。 |
| `items[].state` | `enum<string>` | 是 | 当前发布状态。 |
| `items[].author_user_ref` | `string` | 否 | 作者公开用户引用，可用于人物和世界作者筛选。 |
| `items[].author_name` | `string` | 否 | 发布时的作者展示名称。 |
| `items[].title` | `string` | 否 | 已发布标题快照。 |
| `items[].text_content` | `string` | 否 | 已发布纯文本正文；不隐式同步源快记新版本。 |
| `items[].text_truncated` | `boolean` | 否 | 列表正文是否截断；列表最多 512 个 Unicode 码点，为 true 时用 batch_get_world_records 读取完整公开正文。 |
| `items[].record_type` | `enum<string>` | 否 | 世界动态类型。 |
| `items[].parent_record_uid` | `string` | 否 | 直接父世界快记 UID；缺省表示顶层动态。 |
| `items[].tags` | `array<string>` | 否 | 发布快照的标签。 |
| `items[].published_at` | `integer` | 否 | 发布时间，Unix 毫秒。 |
| `items[].created_at` | `integer` | 否 | 源快记业务时间，Unix 毫秒。 |
| `items[].publication_version` | `integer` | 是 | World 当前写入水位，用于条件发布和撤回；missing 为 -1。不能传源 Record 版本。 |
| `items[].files` | `array<object>` | 否 | 已冻结的附件元数据，不返回内部对象存储路径或凭据。 |
| `items[].files[].file_asset_uid` | `string` | 是 | 已发布附件的 file-domain 资产 UID。 |
| `items[].files[].file_name` | `string` | 是 | 附件展示名称。 |
| `items[].files[].mime_type` | `string` | 是 | 附件 MIME 类型。 |
| `items[].files[].media_type` | `string` | 是 | 附件展示类型：image、video、voice 或 file。 |
| `items[].files[].size` | `integer` | 是 | 附件大小，字节。 |
| `items[].files[].duration_millis` | `integer` | 否 | 音视频时长，毫秒。 |
| `items[].extension` | `null or object` | 否 | 插件发布动态快照；不代表插件当前仍然可安装。 |
| `items[].extension.extension_id` | `string` | 是 | 市集插件身份，当前可安装性仍以市集为准。 |
| `items[].extension.version` | `string` | 是 | 此次发布冻结的插件版本。 |
| `items[].extension.name` | `string` | 是 | 此次发布的插件名称。 |
| `items[].extension.description` | `string` | 否 | 此次发布的插件说明。 |
| `items[].extension.share_url` | `string` | 否 | 插件公开分享页地址。 |
| `has_more` | `boolean` | 是 | 是否存在下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].record_type` | `record` | 普通源快记的世界发布快照。 |
| `items[].record_type` | `extension_publication` | 插件发布事件的世界展示快照，不是可编辑快记。 |
| `items[].state` | `published` | 快照已公开且通过审核。 |
| `items[].state` | `pending` | 已提交公开，但正在等待审核。 |
| `items[].state` | `rejected` | 该快照未通过审核，只向本人提供。 |
| `items[].state` | `unpublished` | 该快照已经撤回公开。 |
| `items[].state` | `missing` | 快照不存在或当前无权读取。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": []
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 读取世界发布快照 {#batchGetWorldRecords}

`POST /api/v1/world/records/batch-get`

按快记 UID 读取当前可见发布事实及写入水位；源记录版本与 World 水位分别使用。

Operation ID：`batchGetWorldRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `record_uids` | `array<string>` | 是 | 要读取的世界快照 UID，1 到 10 个，不重复。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/world/records/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"record_uids":["record-1"]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的世界发布快照。 |
| `items[].record_uid` | `string` | 是 | 世界快照对应的源快记 UID。 |
| `items[].state` | `enum<string>` | 是 | 当前发布状态。 |
| `items[].author_user_ref` | `string` | 否 | 作者公开用户引用，可用于人物和世界作者筛选。 |
| `items[].author_name` | `string` | 否 | 发布时的作者展示名称。 |
| `items[].title` | `string` | 否 | 已发布标题快照。 |
| `items[].text_content` | `string` | 否 | 已发布纯文本正文；不隐式同步源快记新版本。 |
| `items[].text_truncated` | `boolean` | 否 | 列表正文是否截断；列表最多 512 个 Unicode 码点，为 true 时用 batch_get_world_records 读取完整公开正文。 |
| `items[].record_type` | `enum<string>` | 否 | 世界动态类型。 |
| `items[].parent_record_uid` | `string` | 否 | 直接父世界快记 UID；缺省表示顶层动态。 |
| `items[].tags` | `array<string>` | 否 | 发布快照的标签。 |
| `items[].published_at` | `integer` | 否 | 发布时间，Unix 毫秒。 |
| `items[].created_at` | `integer` | 否 | 源快记业务时间，Unix 毫秒。 |
| `items[].publication_version` | `integer` | 是 | World 当前写入水位，用于条件发布和撤回；missing 为 -1。不能传源 Record 版本。 |
| `items[].files` | `array<object>` | 否 | 已冻结的附件元数据，不返回内部对象存储路径或凭据。 |
| `items[].files[].file_asset_uid` | `string` | 是 | 已发布附件的 file-domain 资产 UID。 |
| `items[].files[].file_name` | `string` | 是 | 附件展示名称。 |
| `items[].files[].mime_type` | `string` | 是 | 附件 MIME 类型。 |
| `items[].files[].media_type` | `string` | 是 | 附件展示类型：image、video、voice 或 file。 |
| `items[].files[].size` | `integer` | 是 | 附件大小，字节。 |
| `items[].files[].duration_millis` | `integer` | 否 | 音视频时长，毫秒。 |
| `items[].extension` | `null or object` | 否 | 插件发布动态快照；不代表插件当前仍然可安装。 |
| `items[].extension.extension_id` | `string` | 是 | 市集插件身份，当前可安装性仍以市集为准。 |
| `items[].extension.version` | `string` | 是 | 此次发布冻结的插件版本。 |
| `items[].extension.name` | `string` | 是 | 此次发布的插件名称。 |
| `items[].extension.description` | `string` | 否 | 此次发布的插件说明。 |
| `items[].extension.share_url` | `string` | 否 | 插件公开分享页地址。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].record_type` | `record` | 普通源快记的世界发布快照。 |
| `items[].record_type` | `extension_publication` | 插件发布事件的世界展示快照，不是可编辑快记。 |
| `items[].state` | `published` | 快照已公开且通过审核。 |
| `items[].state` | `pending` | 已提交公开，但正在等待审核。 |
| `items[].state` | `rejected` | 该快照未通过审核，只向本人提供。 |
| `items[].state` | `unpublished` | 该快照已经撤回公开。 |
| `items[].state` | `missing` | 快照不存在或当前无权读取。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "publication_version": -1,
        "record_uid": "record-1",
        "state": "missing"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询世界评论 {#queryWorldReplies}

`POST /api/v1/world/replies/query`

分页读取当前公开父快记的直接子延展，不展开无限评论树，不推进已读水位。

Operation ID：`queryWorldReplies`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `parent_record_uid` | `string` | 是 | 当前公开且审核可见的父快记 UID；只查询直接子延展。 |
| `limit` | `integer` | 否 | 每页条数，1 到 100，缺省 20。 |
| `page_cursor` | `string` | 否 | 上一页游标；续页保持父快记不变。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/world/replies/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"parent_record_uid":"record-1","limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 当前可见的世界动态；分页反映实时事实，不保证跨页快照隔离。 |
| `items[].record_uid` | `string` | 是 | 世界快照对应的源快记 UID。 |
| `items[].state` | `enum<string>` | 是 | 当前发布状态。 |
| `items[].author_user_ref` | `string` | 否 | 作者公开用户引用，可用于人物和世界作者筛选。 |
| `items[].author_name` | `string` | 否 | 发布时的作者展示名称。 |
| `items[].title` | `string` | 否 | 已发布标题快照。 |
| `items[].text_content` | `string` | 否 | 已发布纯文本正文；不隐式同步源快记新版本。 |
| `items[].text_truncated` | `boolean` | 否 | 列表正文是否截断；列表最多 512 个 Unicode 码点，为 true 时用 batch_get_world_records 读取完整公开正文。 |
| `items[].record_type` | `enum<string>` | 否 | 世界动态类型。 |
| `items[].parent_record_uid` | `string` | 否 | 直接父世界快记 UID；缺省表示顶层动态。 |
| `items[].tags` | `array<string>` | 否 | 发布快照的标签。 |
| `items[].published_at` | `integer` | 否 | 发布时间，Unix 毫秒。 |
| `items[].created_at` | `integer` | 否 | 源快记业务时间，Unix 毫秒。 |
| `items[].publication_version` | `integer` | 是 | World 当前写入水位，用于条件发布和撤回；missing 为 -1。不能传源 Record 版本。 |
| `items[].files` | `array<object>` | 否 | 已冻结的附件元数据，不返回内部对象存储路径或凭据。 |
| `items[].files[].file_asset_uid` | `string` | 是 | 已发布附件的 file-domain 资产 UID。 |
| `items[].files[].file_name` | `string` | 是 | 附件展示名称。 |
| `items[].files[].mime_type` | `string` | 是 | 附件 MIME 类型。 |
| `items[].files[].media_type` | `string` | 是 | 附件展示类型：image、video、voice 或 file。 |
| `items[].files[].size` | `integer` | 是 | 附件大小，字节。 |
| `items[].files[].duration_millis` | `integer` | 否 | 音视频时长，毫秒。 |
| `items[].extension` | `null or object` | 否 | 插件发布动态快照；不代表插件当前仍然可安装。 |
| `items[].extension.extension_id` | `string` | 是 | 市集插件身份，当前可安装性仍以市集为准。 |
| `items[].extension.version` | `string` | 是 | 此次发布冻结的插件版本。 |
| `items[].extension.name` | `string` | 是 | 此次发布的插件名称。 |
| `items[].extension.description` | `string` | 否 | 此次发布的插件说明。 |
| `items[].extension.share_url` | `string` | 否 | 插件公开分享页地址。 |
| `has_more` | `boolean` | 是 | 是否存在下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].record_type` | `record` | 普通源快记的世界发布快照。 |
| `items[].record_type` | `extension_publication` | 插件发布事件的世界展示快照，不是可编辑快记。 |
| `items[].state` | `published` | 快照已公开且通过审核。 |
| `items[].state` | `pending` | 已提交公开，但正在等待审核。 |
| `items[].state` | `rejected` | 该快照未通过审核，只向本人提供。 |
| `items[].state` | `unpublished` | 该快照已经撤回公开。 |
| `items[].state` | `missing` | 快照不存在或当前无权读取。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": []
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 发布快记到世界 {#publishWorldRecords}

`POST /api/v1/world/records/publish`

用户明确要求公开时调用。先读取源 Record 版本和 World 水位；首次 World 发布传 -1。只发布指定版本的本人正文与已验证附件，可指定父动态作为评论；不创建源记录。冲突时重读并确认意图，未知结果先核对当前事实。

Operation ID：`publishWorldRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 条发布指令；发布原记录，不创建或修改源记录。 |
| `items[].item_id` | `string` | 是 | 本批次唯一关联标识，最多 64 字节。 |
| `items[].record_uid` | `string` | 是 | 本人创作且可读取的源快记 UID；先通过记录工具取得。 |
| `items[].source_version` | `integer` | 是 | 待发布的 Record 当前版本；先读取源快记，不能用 World 水位替代。 |
| `items[].expected_publication_version` | `integer` | 是 | 期望 World 写入水位；首次发布传 -1，已有快照使用读取结果。 |
| `items[].parent_record_uid` | `string` | 否 | 可选直接父世界快记 UID，用于发布评论；已发布关系不可改挂。 |
| `items[].tags` | `array<string>` | 否 | 本次发布的完整标签集合，最多 20 个；缺省为空。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/world/records/publish' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"post-1","record_uid":"record-1","source_version":1,"expected_publication_version":-1}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的逐项结果；一项失败不掩盖其他项的进度。 |
| `items[].item_id` | `string` | 是 | 对应输入项的关联标识。 |
| `items[].record_uid` | `string` | 是 | 本项世界快记 UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项执行结论。 |
| `items[].publication_version` | `integer` | 否 | 成功写入的 World 水位；后续变化可能使其过期。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].status` | `published` | 快照已公开且通过审核。 |
| `items[].status` | `pending` | 已提交公开，但正在等待审核。 |
| `items[].status` | `unpublished` | 该快照已经撤回公开。 |
| `items[].status` | `conflict` | 当前事实已变化；重新读取并确认操作意图。 |
| `items[].status` | `unavailable` | 目标或父动态不支持此次操作，或当前无权操作。 |
| `items[].status` | `source_unavailable` | 源记录已变化、受保护、不可发布或附件不可用。 |
| `items[].status` | `phone_required` | 账号需要绑定手机号才能发布世界内容。 |
| `items[].status` | `unknown` | 未能确定本项最终结果；读取当前事实核对后再决定。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "item_id": "post-1",
        "publication_version": 1700000000000,
        "record_uid": "record-1",
        "status": "published"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 撤回世界发布 {#unpublishWorldRecords}

`POST /api/v1/world/records/unpublish`

按本人发布快照水位撤回公开；不删除源记录或其他人的评论。旧请求重试不能重新公开，冲突后需重读当前事实。

Operation ID：`unpublishWorldRecords`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 条撤回指令；不删除源快记或其他人的评论。 |
| `items[].item_id` | `string` | 是 | 本批次唯一关联标识，最多 64 字节。 |
| `items[].record_uid` | `string` | 是 | 本人要撤回的世界快记 UID。 |
| `items[].expected_publication_version` | `integer` | 是 | 读取到的 World 当前写入水位；撤回只作用于该快照。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/world/records/unpublish' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"post-1","record_uid":"record-1","expected_publication_version":1700000000000}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的逐项结果；一项失败不掩盖其他项的进度。 |
| `items[].item_id` | `string` | 是 | 对应输入项的关联标识。 |
| `items[].record_uid` | `string` | 是 | 本项世界快记 UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项执行结论。 |
| `items[].publication_version` | `integer` | 否 | 成功写入的 World 水位；后续变化可能使其过期。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].status` | `published` | 快照已公开且通过审核。 |
| `items[].status` | `pending` | 已提交公开，但正在等待审核。 |
| `items[].status` | `unpublished` | 该快照已经撤回公开。 |
| `items[].status` | `conflict` | 当前事实已变化；重新读取并确认操作意图。 |
| `items[].status` | `unavailable` | 目标或父动态不支持此次操作，或当前无权操作。 |
| `items[].status` | `source_unavailable` | 源记录已变化、受保护、不可发布或附件不可用。 |
| `items[].status` | `phone_required` | 账号需要绑定手机号才能发布世界内容。 |
| `items[].status` | `unknown` | 未能确定本项最终结果；读取当前事实核对后再决定。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "item_id": "post-1",
        "publication_version": 1700000000001,
        "record_uid": "record-1",
        "status": "unpublished"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询已有世界候选 {#queryWorldCandidates}

`POST /api/v1/world/candidates/query`

读取已有待处理候选，不生成推荐、不处理候选、不标记已读。候选摘要可能早于原记录；发布前使用 batch_get_records 核对当前版本与正文。

Operation ID：`queryWorldCandidates`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `limit` | `integer` | 否 | 返回已有待处理候选的上限，1 到 100，缺省 20；按推荐置信度排序。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/world/candidates/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 已有待处理候选；本次查询不生成、处理或标记候选。 |
| `items[].record_uid` | `string` | 是 | 候选源快记 UID；发布前读取其当前版本和正文。 |
| `items[].summary` | `string` | 是 | 已生成的候选摘要，可能早于源快记当前版本。 |
| `items[].reason` | `string` | 是 | 已有候选的推荐理由。 |
| `items[].confidence` | `number` | 是 | 推荐置信度，0 到 1。 |
| `items[].created_at` | `integer` | 是 | 候选生成时间，Unix 毫秒。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": []
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 读取世界互动摘要 {#getWorldInteractionSummary}

`POST /api/v1/world/interactions/summary`

只读取未查看数量和本次捕获的序号；不会因为 AI 查询而清空用户未读。

Operation ID：`getWorldInteractionSummary`

#### 请求字段

无字段，请求体使用 `{}`。

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/world/interactions/summary' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `unread_count` | `integer` | 是 | 截至本次捕获水位的未查看互动数。 |
| `seen_through_sequence` | `integer` | 是 | 本次捕获的互动序号；明确标记查看时传回。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "seen_through_sequence": 20,
    "unread_count": 2
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 标记世界互动已查看 {#markWorldInteractionsViewed}

`POST /api/v1/world/interactions/mark-viewed`

用户明确要求或已实际展示相应互动摘要后，传入当时捕获的 seen_through_sequence；不会标记之后到达的新互动。

Operation ID：`markWorldInteractionsViewed`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `seen_through_sequence` | `integer` | 是 | 已向用户展示的互动摘要水位，必须大于零。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/world/interactions/mark-viewed' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"seen_through_sequence":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `read_sequence` | `integer` | 是 | 此次确认的互动水位；不会清除之后到达的互动。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "read_sequence": 20
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

## 机器人 {#rest-bot}

### 查询本人机器人 {#queryBots}

`POST /api/v1/bots/query`

按名称、说明或提供方分页读取本人 Bot，不创建会话、不连接 runtime。

Operation ID：`queryBots`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `keyword` | `string` | 否 | 按本人 Bot 的名称或说明匹配，最多 100 字符。 |
| `provider` | `enum<string>` | 否 | 可选提供方筛选。 |
| `limit` | `integer` | 否 | 每页 1 到 100 条，缺省 20。 |
| `page_cursor` | `string` | 否 | 上一页返回的游标，续页保持筛选条件不变。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `provider` | `webhook` | 用户以 Bot 身份向明确目标发布消息。 |
| `provider` | `openclaw` | 用户请求由已接入的 OpenClaw runtime 异步处理。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 本人可读取的 Bot，不返回 token 或接入凭据。 |
| `items[].bot_uid` | `string` | 是 | Bot 稳定身份；与用户、群聊、App 内置 Agent 身份不同。 |
| `items[].found` | `boolean` | 是 | 是否为本人当前可读取的 Bot；缺失与无权读取统一返回 false。 |
| `items[].name` | `string` | 否 | Bot 名称。 |
| `items[].description` | `string` | 否 | Bot 说明。 |
| `items[].avatar` | `string` | 否 | Bot 头像引用。 |
| `items[].provider` | `enum<string>` | 否 | 提供方：webhook 或 openclaw。 |
| `items[].status` | `enum<string>` | 否 | 当前 Bot 运行状态；不代表某条请求已经完成。 |
| `items[].revision` | `integer` | 否 | 当前 owner 写入水位，用于资料更新和删除；不是时间参数。 |
| `items[].created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].mention_entry_enabled` | `boolean` | 是 | 是否显示 Bot 的提及入口；不授予群上下文读取权限。 |
| `has_more` | `boolean` | 是 | 是否还有下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].provider` | `webhook` | 用户以 Bot 身份向明确目标发布消息。 |
| `items[].provider` | `openclaw` | 用户请求由已接入的 OpenClaw runtime 异步处理。 |
| `items[].status` | `offline` | Bot 当前离线。 |
| `items[].status` | `online` | Bot 当前在线。 |
| `items[].status` | `default` | 无需运行连接的默认状态。 |
| `items[].status` | `deleted` | Bot 已删除。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": []
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 读取机器人资料 {#batchGetBots}

`POST /api/v1/bots/batch-get`

按 Bot UID 读取本人资料和当前写入水位；不返回 token，不读取 App 内置 Agent。

Operation ID：`batchGetBots`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uids` | `array<string>` | 是 | 1 到 10 个不重复的 Bot UID。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/batch-get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"bot_uids":["bot-1"]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的查询结果。 |
| `items[].bot_uid` | `string` | 是 | Bot 稳定身份；与用户、群聊、App 内置 Agent 身份不同。 |
| `items[].found` | `boolean` | 是 | 是否为本人当前可读取的 Bot；缺失与无权读取统一返回 false。 |
| `items[].name` | `string` | 否 | Bot 名称。 |
| `items[].description` | `string` | 否 | Bot 说明。 |
| `items[].avatar` | `string` | 否 | Bot 头像引用。 |
| `items[].provider` | `enum<string>` | 否 | 提供方：webhook 或 openclaw。 |
| `items[].status` | `enum<string>` | 否 | 当前 Bot 运行状态；不代表某条请求已经完成。 |
| `items[].revision` | `integer` | 否 | 当前 owner 写入水位，用于资料更新和删除；不是时间参数。 |
| `items[].created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].mention_entry_enabled` | `boolean` | 是 | 是否显示 Bot 的提及入口；不授予群上下文读取权限。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].provider` | `webhook` | 用户以 Bot 身份向明确目标发布消息。 |
| `items[].provider` | `openclaw` | 用户请求由已接入的 OpenClaw runtime 异步处理。 |
| `items[].status` | `offline` | Bot 当前离线。 |
| `items[].status` | `online` | Bot 当前在线。 |
| `items[].status` | `default` | 无需运行连接的默认状态。 |
| `items[].status` | `deleted` | Bot 已删除。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "found": false,
        "mention_entry_enabled": false
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 创建机器人 {#createBots}

`POST /api/v1/bots/create`

明确选择 Webhook 或 OpenClaw，创建本人 Bot 及专属会话。此工具不安装客户端程序，也不把 App 内置 Agent 作为 Bot。重试复用幂等键及原始创建参数。

Operation ID：`createBots`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 项；仅创建账号中的 Bot 及其专属会话，不安装本机运行程序。 |
| `items[].item_id` | `string` | 是 | 本批唯一关联标识，最多 64 字节。 |
| `items[].idempotency_key` | `string` | 是 | 本次创建的稳定幂等键，最多 128 字符，只含字母、数字及 . _ : -；重试必须复用。 |
| `items[].provider` | `enum<string>` | 是 | 选择 Bot 提供方。 |
| `items[].name` | `string` | 是 | Bot 名称，去除首尾空格后为 1 到 100 字符。 |
| `items[].description` | `string` | 否 | Bot 说明，最多 2000 字符。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].provider` | `webhook` | 用户以 Bot 身份向明确目标发布消息。 |
| `items[].provider` | `openclaw` | 用户请求由已接入的 OpenClaw runtime 异步处理。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/create' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"one","idempotency_key":"create-1","provider":"webhook","name":"通知助手"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的逐项结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项结果；unknown 表示需读取事实核对，不能换幂等键盲目重发。 |
| `items[].bot` | `null or object` | 否 | 成功后的当前 Bot 资料。 |
| `items[].bot.bot_uid` | `string` | 是 | Bot 稳定身份；与用户、群聊、App 内置 Agent 身份不同。 |
| `items[].bot.found` | `boolean` | 是 | 是否为本人当前可读取的 Bot；缺失与无权读取统一返回 false。 |
| `items[].bot.name` | `string` | 否 | Bot 名称。 |
| `items[].bot.description` | `string` | 否 | Bot 说明。 |
| `items[].bot.avatar` | `string` | 否 | Bot 头像引用。 |
| `items[].bot.provider` | `enum<string>` | 否 | 提供方：webhook 或 openclaw。 |
| `items[].bot.status` | `enum<string>` | 否 | 当前 Bot 运行状态；不代表某条请求已经完成。 |
| `items[].bot.revision` | `integer` | 否 | 当前 owner 写入水位，用于资料更新和删除；不是时间参数。 |
| `items[].bot.created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].bot.mention_entry_enabled` | `boolean` | 是 | 是否显示 Bot 的提及入口；不授予群上下文读取权限。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].bot.provider` | `webhook` | 用户以 Bot 身份向明确目标发布消息。 |
| `items[].bot.provider` | `openclaw` | 用户请求由已接入的 OpenClaw runtime 异步处理。 |
| `items[].bot.status` | `offline` | Bot 当前离线。 |
| `items[].bot.status` | `online` | Bot 当前在线。 |
| `items[].bot.status` | `default` | 无需运行连接的默认状态。 |
| `items[].bot.status` | `deleted` | Bot 已删除。 |
| `items[].status` | `succeeded` | 当前操作已完成；发送请求不表示 Bot 已回答。 |
| `items[].status` | `conflict` | 事实已变化，重读并确认意图。 |
| `items[].status` | `unavailable` | 目标不支持该操作或当前无权操作。 |
| `items[].status` | `unknown` | 结果无法确定，使用原身份核对事实再决定重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "item_id": "one",
        "status": "unknown"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 更新机器人资料 {#updateBotProfiles}

`POST /api/v1/bots/profile/update`

读取 Bot 水位后提交完整名称和说明。头像及提及入口可选；不改变 runtime、群上下文授权或 Webhook 安全设置。

Operation ID：`updateBotProfiles`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 条本人 Bot 资料更新。 |
| `items[].item_id` | `string` | 是 | 本批唯一关联标识，最多 64 字节。 |
| `items[].bot_uid` | `string` | 是 | 本人 Bot UID。 |
| `items[].expected_revision` | `integer` | 是 | 读取到的 Bot owner 水位，过期返回冲突。 |
| `items[].name` | `string` | 是 | 完整名称，1 到 100 字符。 |
| `items[].description` | `string` | 是 | 完整说明，最多 2000 字符；空字符串清空说明。 |
| `items[].avatar` | `null or string` | 否 | 头像引用；省略保留，空字符串清空。 |
| `items[].mention_entry_enabled` | `null or boolean` | 否 | 可选提及入口开关；省略保留。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/profile/update' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"one","bot_uid":"bot-1","expected_revision":100,"name":"通知助手","description":"发布团队通知"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的逐项结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项结果；unknown 表示需读取事实核对，不能换幂等键盲目重发。 |
| `items[].bot` | `null or object` | 否 | 成功后的当前 Bot 资料。 |
| `items[].bot.bot_uid` | `string` | 是 | Bot 稳定身份；与用户、群聊、App 内置 Agent 身份不同。 |
| `items[].bot.found` | `boolean` | 是 | 是否为本人当前可读取的 Bot；缺失与无权读取统一返回 false。 |
| `items[].bot.name` | `string` | 否 | Bot 名称。 |
| `items[].bot.description` | `string` | 否 | Bot 说明。 |
| `items[].bot.avatar` | `string` | 否 | Bot 头像引用。 |
| `items[].bot.provider` | `enum<string>` | 否 | 提供方：webhook 或 openclaw。 |
| `items[].bot.status` | `enum<string>` | 否 | 当前 Bot 运行状态；不代表某条请求已经完成。 |
| `items[].bot.revision` | `integer` | 否 | 当前 owner 写入水位，用于资料更新和删除；不是时间参数。 |
| `items[].bot.created_at` | `integer` | 否 | 创建时间，Unix 毫秒。 |
| `items[].bot.mention_entry_enabled` | `boolean` | 是 | 是否显示 Bot 的提及入口；不授予群上下文读取权限。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].bot.provider` | `webhook` | 用户以 Bot 身份向明确目标发布消息。 |
| `items[].bot.provider` | `openclaw` | 用户请求由已接入的 OpenClaw runtime 异步处理。 |
| `items[].bot.status` | `offline` | Bot 当前离线。 |
| `items[].bot.status` | `online` | Bot 当前在线。 |
| `items[].bot.status` | `default` | 无需运行连接的默认状态。 |
| `items[].bot.status` | `deleted` | Bot 已删除。 |
| `items[].status` | `succeeded` | 当前操作已完成；发送请求不表示 Bot 已回答。 |
| `items[].status` | `conflict` | 事实已变化，重读并确认意图。 |
| `items[].status` | `unavailable` | 目标不支持该操作或当前无权操作。 |
| `items[].status` | `unknown` | 结果无法确定，使用原身份核对事实再决定重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "item_id": "one",
        "status": "conflict"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 删除机器人 {#deleteBots}

`POST /api/v1/bots/delete`

用户明确要求删除时调用；沿既有 Bot 生命周期停用 Bot、撤销绑定并关闭专属会话，不删除其他人的普通会话或消息。

Operation ID：`deleteBots`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 条删除指令；沿 Bot 既有生命周期撤销绑定和关闭专属会话。 |
| `items[].item_id` | `string` | 是 | 本批唯一关联标识。 |
| `items[].bot_uid` | `string` | 是 | 要删除的本人 Bot UID。 |
| `items[].expected_revision` | `integer` | 是 | 读取到的当前 Bot 水位。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/delete' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"one","bot_uid":"bot-1","expected_revision":100}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的删除结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项结果；unknown 表示需读取事实核对，不能换幂等键盲目重发。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].status` | `succeeded` | 当前操作已完成；发送请求不表示 Bot 已回答。 |
| `items[].status` | `conflict` | 事实已变化，重读并确认意图。 |
| `items[].status` | `unavailable` | 目标不支持该操作或当前无权操作。 |
| `items[].status` | `unknown` | 结果无法确定，使用原身份核对事实再决定重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "item_id": "one",
        "status": "succeeded"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 列举机器人群绑定 {#listGroupBotBindings}

`POST /api/v1/bots/group-bindings/list`

分页读取本人 Bot 的真实 Chat 群绑定和上下文权限，包含已移除水位。指定 chat_session_uid 时精确读取该群绑定，允许 Bot owner 或该群当前群主；群主可据此移除他人的 Bot。

Operation ID：`listGroupBotBindings`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uid` | `string` | 是 | 目标 Bot UID；不指定群时仅允许本人 Bot。 |
| `chat_session_uid` | `string` | 否 | 精确读取此群的绑定；允许 Bot owner 或该群当前群主，不接受分页游标。 |
| `limit` | `integer` | 否 | 每页 1 到 100 条，缺省 20。 |
| `page_cursor` | `string` | 否 | 上一页游标，续页保持 Bot 不变。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/group-bindings/list' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"bot_uid":"bot-1","limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | Chat 群绑定，包含已移除事实供条件重装；不把旧主题伪装成 Chat 群。 |
| `items[].bot_uid` | `string` | 是 | Bot UID。 |
| `items[].chat_session_uid` | `string` | 是 | Chat owner 的真实群聊 UID。 |
| `items[].state` | `enum<string>` | 是 | installed 或 removed。 |
| `items[].revision` | `integer` | 是 | 当前群绑定水位。 |
| `items[].allow_read_group_members` | `boolean` | 是 | 是否允许 Bot 读取当前群成员。 |
| `items[].allow_read_group_messages` | `boolean` | 是 | 是否允许 Bot 读取当前群消息。 |
| `has_more` | `boolean` | 是 | 是否存在下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页不透明游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].state` | `installed` | 当前已安装。 |
| `items[].state` | `removed` | 当前已移除，保留水位供条件重装。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "has_more": false,
    "items": []
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 安装群机器人 {#installGroupBots}

`POST /api/v1/bots/group-bindings/install`

仅将本人 Bot 安装到明确指定且允许添加 Bot 的 Chat 群。首次绑定水位传 -1；重新安装使用已移除水位。首次安装和重装不自动授予群成员或群消息读取权限。

Operation ID：`installGroupBots`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 条明确的 Bot 和群绑定指令。 |
| `items[].item_id` | `string` | 是 | 本批唯一关联标识。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].chat_session_uid` | `string` | 是 | 目标 Chat 群 UID；先通过会话工具确认。 |
| `items[].expected_binding_revision` | `integer` | 是 | 读取的绑定水位；首次安装传 -1，其余操作使用当前值。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/group-bindings/install' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"one","bot_uid":"bot-1","chat_session_uid":"chat-1","expected_binding_revision":-1}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的逐项结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项结果；unknown 表示需读取事实核对，不能换幂等键盲目重发。 |
| `items[].chat_session_uid` | `string` | 是 | 目标群 UID。 |
| `items[].binding` | `null or object` | 否 | 成功后的当前绑定与授权。 |
| `items[].binding.bot_uid` | `string` | 是 | Bot UID。 |
| `items[].binding.chat_session_uid` | `string` | 是 | Chat owner 的真实群聊 UID。 |
| `items[].binding.state` | `enum<string>` | 是 | installed 或 removed。 |
| `items[].binding.revision` | `integer` | 是 | 当前群绑定水位。 |
| `items[].binding.allow_read_group_members` | `boolean` | 是 | 是否允许 Bot 读取当前群成员。 |
| `items[].binding.allow_read_group_messages` | `boolean` | 是 | 是否允许 Bot 读取当前群消息。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].binding.state` | `installed` | 当前已安装。 |
| `items[].binding.state` | `removed` | 当前已移除，保留水位供条件重装。 |
| `items[].status` | `succeeded` | 当前操作已完成；发送请求不表示 Bot 已回答。 |
| `items[].status` | `conflict` | 事实已变化，重读并确认意图。 |
| `items[].status` | `unavailable` | 目标不支持该操作或当前无权操作。 |
| `items[].status` | `unknown` | 结果无法确定，使用原身份核对事实再决定重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "chat_session_uid": "chat-1",
        "item_id": "one",
        "status": "conflict"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 移除群机器人 {#removeGroupBots}

`POST /api/v1/bots/group-bindings/remove`

按当前绑定水位移除指定群中的 Bot，保留 Bot 本身；只允许 Bot 本人 owner 或目标群当前群主操作。旧移除请求不能覆盖后来的重新安装。

Operation ID：`removeGroupBots`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 条明确的 Bot 和群绑定指令。 |
| `items[].item_id` | `string` | 是 | 本批唯一关联标识。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].chat_session_uid` | `string` | 是 | 目标 Chat 群 UID；先通过会话工具确认。 |
| `items[].expected_binding_revision` | `integer` | 是 | 读取的绑定水位；首次安装传 -1，其余操作使用当前值。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/group-bindings/remove' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"one","bot_uid":"bot-1","chat_session_uid":"chat-1","expected_binding_revision":100}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的逐项结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项结果；unknown 表示需读取事实核对，不能换幂等键盲目重发。 |
| `items[].chat_session_uid` | `string` | 是 | 目标群 UID。 |
| `items[].binding` | `null or object` | 否 | 成功后的当前绑定与授权。 |
| `items[].binding.bot_uid` | `string` | 是 | Bot UID。 |
| `items[].binding.chat_session_uid` | `string` | 是 | Chat owner 的真实群聊 UID。 |
| `items[].binding.state` | `enum<string>` | 是 | installed 或 removed。 |
| `items[].binding.revision` | `integer` | 是 | 当前群绑定水位。 |
| `items[].binding.allow_read_group_members` | `boolean` | 是 | 是否允许 Bot 读取当前群成员。 |
| `items[].binding.allow_read_group_messages` | `boolean` | 是 | 是否允许 Bot 读取当前群消息。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].binding.state` | `installed` | 当前已安装。 |
| `items[].binding.state` | `removed` | 当前已移除，保留水位供条件重装。 |
| `items[].status` | `succeeded` | 当前操作已完成；发送请求不表示 Bot 已回答。 |
| `items[].status` | `conflict` | 事实已变化，重读并确认意图。 |
| `items[].status` | `unavailable` | 目标不支持该操作或当前无权操作。 |
| `items[].status` | `unknown` | 结果无法确定，使用原身份核对事实再决定重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "chat_session_uid": "chat-1",
        "item_id": "one",
        "status": "conflict"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 设置机器人群读取授权 {#setGroupBotContextPermissions}

`POST /api/v1/bots/group-bindings/context-permissions/set`

由 Bot owner 明确设置指定已安装群的成员和消息读取权限。两项授权分别表达，不因安装或发送消息隐式放开。

Operation ID：`setGroupBotContextPermissions`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 项，仅修改已安装 Bot 在指定群的读取授权。 |
| `items[].item_id` | `string` | 是 | 本批唯一关联标识。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].chat_session_uid` | `string` | 是 | 目标 Chat 群 UID；先通过会话工具确认。 |
| `items[].expected_binding_revision` | `integer` | 是 | 读取的绑定水位；首次安装传 -1，其余操作使用当前值。 |
| `items[].allow_read_group_members` | `boolean` | 是 | 是否授权读取群成员。 |
| `items[].allow_read_group_messages` | `boolean` | 是 | 是否授权读取群消息。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/group-bindings/context-permissions/set' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"one","bot_uid":"bot-1","chat_session_uid":"chat-1","expected_binding_revision":100,"allow_read_group_members":false,"allow_read_group_messages":true}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的逐项结果。 |
| `items[].item_id` | `string` | 是 | 对应输入项。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项结果；unknown 表示需读取事实核对，不能换幂等键盲目重发。 |
| `items[].chat_session_uid` | `string` | 是 | 目标群 UID。 |
| `items[].binding` | `null or object` | 否 | 成功后的当前绑定与授权。 |
| `items[].binding.bot_uid` | `string` | 是 | Bot UID。 |
| `items[].binding.chat_session_uid` | `string` | 是 | Chat owner 的真实群聊 UID。 |
| `items[].binding.state` | `enum<string>` | 是 | installed 或 removed。 |
| `items[].binding.revision` | `integer` | 是 | 当前群绑定水位。 |
| `items[].binding.allow_read_group_members` | `boolean` | 是 | 是否允许 Bot 读取当前群成员。 |
| `items[].binding.allow_read_group_messages` | `boolean` | 是 | 是否允许 Bot 读取当前群消息。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].binding.state` | `installed` | 当前已安装。 |
| `items[].binding.state` | `removed` | 当前已移除，保留水位供条件重装。 |
| `items[].status` | `succeeded` | 当前操作已完成；发送请求不表示 Bot 已回答。 |
| `items[].status` | `conflict` | 事实已变化，重读并确认意图。 |
| `items[].status` | `unavailable` | 目标不支持该操作或当前无权操作。 |
| `items[].status` | `unknown` | 结果无法确定，使用原身份核对事实再决定重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "chat_session_uid": "chat-1",
        "item_id": "one",
        "status": "conflict"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 定位机器人专属会话 {#resolveBotConversations}

`POST /api/v1/bots/conversations/resolve`

只定位本人 Bot 的有效 Chat 专属会话，返回 chat_session_uid。缺失或关闭时 found 为 false，不回退旧服务、不创建或迁移会话。

Operation ID：`resolveBotConversations`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uids` | `array<string>` | 是 | 1 到 10 个不重复的 Bot UID。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/conversations/resolve' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"bot_uids":["bot-1"]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入 Bot UID 同序的既有会话定位结果。 |
| `items[].bot_uid` | `string` | 是 | 本人 Bot UID。 |
| `items[].found` | `boolean` | 是 | 是否存在当前可用的 Chat 专属会话；缺失或关闭时为 false，查询不会创建或迁移会话。 |
| `items[].kind` | `enum<string>` | 否 | 找到会话时固定为 chat。 |
| `items[].chat_session_uid` | `string` | 否 | 找到会话时返回 Chat UID；不能用 Bot UID 或旧主题 UID 替代。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].kind` | `chat` | 真实 Chat 会话。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "found": false
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询机器人会话历史 {#queryBotConversationMessages}

`POST /api/v1/bots/conversations/messages/query`

按本人 Bot 的有效 Chat 专属会话分页或按时间段读取当前可见正文，不标记已读、不触发 Bot；没有有效 Chat 会话时不可读取。

Operation ID：`queryBotConversationMessages`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uid` | `string` | 是 | 本人 Bot UID，仅读取其有效 Chat 专属会话。 |
| `mode` | `enum<string>` | 否 | scan 分页浏览或 range 查询时间段；缺省 scan。 |
| `start_at` | `integer` | 否 | range 起点，Unix 毫秒。 |
| `end_at` | `integer` | 否 | range 终点，Unix 毫秒，必须晚于起点。 |
| `limit` | `integer` | 否 | 每页 1 到 100 条，缺省 20。 |
| `page_cursor` | `string` | 否 | 上一页游标，续页保持 Bot、模式和时间范围不变。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `mode` | `scan` | 分页浏览既有历史。 |
| `mode` | `range` | 读取明确时间范围。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/conversations/messages/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"bot_uid":"bot-1","mode":"scan","limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uid` | `string` | 是 | 当前 Bot UID。 |
| `chat_session_uid` | `string` | 是 | 当前读取的有效 Chat 会话 UID。 |
| `items` | `array<object>` | 是 | 当前可见历史消息，不推进已读、不触发 Bot。 |
| `items[].record_uid` | `string` | 是 | 当前会话 owner 的消息 UID；不据此推断为本人可编辑的 Record。 |
| `items[].sequence` | `integer` | 是 | Chat 会话中的正整数消息序号。 |
| `items[].speaker_kind` | `enum<string>` | 是 | Chat owner 提供的明确身份：user 或 bot，不能按名称推断。 |
| `items[].speaker_name` | `string` | 否 | 消息发送者的展示名称。 |
| `items[].text_content` | `string` | 是 | 当前可见的消息正文。 |
| `items[].send_at` | `integer` | 是 | 消息时间，Unix 毫秒。 |
| `has_more` | `boolean` | 是 | 是否存在下一页。 |
| `next_page_cursor` | `string` | 否 | 下一页游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].speaker_kind` | `user` | 真实用户发送的消息。 |
| `items[].speaker_kind` | `bot` | 明确 Bot 身份发送的消息。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "bot_uid": "bot-1",
    "chat_session_uid": "chat-1",
    "has_more": false,
    "items": []
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 查询机器人请求结果 {#queryBotRequestResult}

`POST /api/v1/bots/requests/result/query`

按 send_bot_requests 返回的源消息 UID 读取准确执行状态和关联回复。受理、回复组结束与执行完成分别表达。completed 可以没有回复；unknown 时不能换键重发。轮询从首页开始，不按历史时间猜答案。

Operation ID：`queryBotRequestResult`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uid` | `string` | 是 | 本人 OpenClaw Bot UID。 |
| `source_record_uid` | `string` | 是 | send_bot_requests 返回的用户消息 record_uid，不能填写回复 UID。 |
| `limit` | `integer` | 否 | 每页回复 1 到 100 条，缺省 20。 |
| `page_cursor` | `string` | 否 | 本轮读取的下一页游标；重新轮询请求时从首页开始，执行期间可能新增回复。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/requests/result/query' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"bot_uid":"bot-1","source_record_uid":"record-1","limit":20}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uid` | `string` | 是 | 当前 Bot UID。 |
| `source_record_uid` | `string` | 是 | 本次查询的源消息 UID。 |
| `status` | `enum<string>` | 是 | pending 仍在执行窗口；completed 收到明确完成；failed 明确失败；unknown 无法确认，不得换键盲目重执行。 |
| `accepted_at` | `integer` | 否 | 持久受理时间，Unix 毫秒；历史无回执时缺省。 |
| `finished_at` | `integer` | 否 | 记录最终观察结果的 Unix 毫秒时间；unknown 不保证外部业务未执行。 |
| `items` | `array<object>` | 是 | 精确关联的回复引用及当前可见正文；完成可以没有回复，分页顺序不表示回复时间先后。 |
| `items[].record_uid` | `string` | 是 | 此请求已写入的回复消息 UID。 |
| `items[].reply_group_id` | `string` | 否 | runtime 提供的回复组标识，仅用于关联，不表示完成。 |
| `items[].phase` | `string` | 否 | runtime 回复阶段，仅作展示。 |
| `items[].sequence` | `integer` | 是 | 回复组内顺序，不是 Chat 会话消息序号。 |
| `items[].is_final` | `boolean` | 是 | 此回复组是否结束，不表示整个请求执行完成。 |
| `items[].message` | `null or object` | 否 | 由会话 owner 读取的当前可见正文；消息被删除或不可见时缺省，不能使用缓存绕过权限。 |
| `items[].message.record_uid` | `string` | 是 | 当前会话 owner 的消息 UID；不据此推断为本人可编辑的 Record。 |
| `items[].message.sequence` | `integer` | 是 | Chat 会话中的正整数消息序号。 |
| `items[].message.speaker_kind` | `string` | 是 | Chat owner 提供的明确身份：user 或 bot，不能按名称推断。 |
| `items[].message.speaker_name` | `string` | 否 | 消息发送者的展示名称。 |
| `items[].message.text_content` | `string` | 是 | 当前可见的消息正文。 |
| `items[].message.send_at` | `integer` | 是 | 消息时间，Unix 毫秒。 |
| `has_more` | `boolean` | 是 | 当前还有下一页回复引用。 |
| `next_page_cursor` | `string` | 否 | 不透明续页游标。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `status` | `pending` | 请求已受理，尚无明确完成。 |
| `status` | `completed` | runtime 明确完成，可以没有回复。 |
| `status` | `failed` | 已观察到失败，不代表外部动作一定未生效。 |
| `status` | `unknown` | 结果无法确定，使用原身份核对事实再决定重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "bot_uid": "bot-1",
    "has_more": false,
    "items": [],
    "source_record_uid": "record-1",
    "status": "unknown"
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 向机器人发送用户请求 {#sendBotRequests}

`POST /api/v1/bots/requests/send`

以当前用户身份向本人 OpenClaw Bot 的专属会话发送文本请求。成功表示消息已写入且投递已受理，回答异步到达。复用原幂等键重试，通过 query_bot_request_result 精确查询执行状态和回复；Webhook Bot 不接收此类请求。

Operation ID：`sendBotRequests`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 条用户请求；写入对应专属会话并交给既有 Bot runtime 异步处理。 |
| `items[].item_id` | `string` | 是 | 本批唯一关联标识。 |
| `items[].bot_uid` | `string` | 是 | 本人 OpenClaw Bot UID；Webhook Bot 不接受运行请求。 |
| `items[].idempotency_key` | `string` | 是 | 本次消息稳定幂等键，最多 128 字符，仅字母、数字及 . _ : -；重试必须复用。 |
| `items[].text_content` | `string` | 是 | 用户发送给 Bot 的文本，最多 10000 字符。 |
| `items[].send_at` | `integer` | 是 | 本次消息的 Unix 毫秒时间，重试时保持不变。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/requests/send' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"one","bot_uid":"bot-1","idempotency_key":"request-1","text_content":"整理今天的重点","send_at":1700000000000}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的结果；成功仅表示接收或发布，不表示 OpenClaw 已回答。 |
| `items[].item_id` | `string` | 是 | 对应输入项。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项结果；unknown 表示需读取事实核对，不能换幂等键盲目重发。 |
| `items[].chat_session_uid` | `string` | 否 | 操作成功时返回消息所在的真实 Chat 会话。 |
| `items[].record_uid` | `string` | 否 | 用户请求写入后的消息 UID；Bot 主动发布以幂等键关联。 |
| `items[].sequence` | `integer` | 否 | 用户请求在 Chat 会话中的消息序号。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].status` | `succeeded` | 当前操作已完成；发送请求不表示 Bot 已回答。 |
| `items[].status` | `conflict` | 事实已变化，重读并确认意图。 |
| `items[].status` | `unavailable` | 目标不支持该操作或当前无权操作。 |
| `items[].status` | `unknown` | 结果无法确定，使用原身份核对事实再决定重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "item_id": "one",
        "status": "unknown"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 以机器人身份发布消息 {#publishBotMessages}

`POST /api/v1/bots/messages/publish`

仅以本人 Webhook Bot 身份向明确的专属会话或一个已安装 Chat 群发布文本。必须明确目标，不广播、不启动 OpenClaw；幂等键应绑定本次目标和正文，重试保持原参数。

Operation ID：`publishBotMessages`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 1 到 10 条本人 Webhook Bot 的定向发布。 |
| `items[].item_id` | `string` | 是 | 本批唯一关联标识。 |
| `items[].bot_uid` | `string` | 是 | 本人 Webhook Bot UID；不能冒用 OpenClaw 身份。 |
| `items[].idempotency_key` | `string` | 是 | 稳定消息幂等键，最多 128 字符，仅字母、数字及 . _ : -。 |
| `items[].target_kind` | `enum<string>` | 是 | 明确选择 direct 专属会话或 group 指定群，不支持广播。 |
| `items[].chat_session_uid` | `string` | 否 | group 时必填的已安装群 UID；direct 时禁止填写。 |
| `items[].text_content` | `string` | 是 | Bot 发布的文本，最多 10000 字符。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].target_kind` | `direct` | 当前 Bot 的专属会话。 |
| `items[].target_kind` | `group` | 显式指定的已安装 Chat 群。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/messages/publish' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"items":[{"item_id":"one","bot_uid":"bot-1","idempotency_key":"publish-1","target_kind":"direct","text_content":"今日任务已完成"}]}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `items` | `array<object>` | 是 | 与输入同序的结果；成功仅表示接收或发布，不表示 OpenClaw 已回答。 |
| `items[].item_id` | `string` | 是 | 对应输入项。 |
| `items[].bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `items[].status` | `enum<string>` | 是 | 逐项结果；unknown 表示需读取事实核对，不能换幂等键盲目重发。 |
| `items[].chat_session_uid` | `string` | 否 | 操作成功时返回消息所在的真实 Chat 会话。 |
| `items[].record_uid` | `string` | 否 | 用户请求写入后的消息 UID；Bot 主动发布以幂等键关联。 |
| `items[].sequence` | `integer` | 否 | 用户请求在 Chat 会话中的消息序号。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `items[].status` | `succeeded` | 当前操作已完成；发送请求不表示 Bot 已回答。 |
| `items[].status` | `conflict` | 事实已变化，重读并确认意图。 |
| `items[].status` | `unavailable` | 目标不支持该操作或当前无权操作。 |
| `items[].status` | `unknown` | 结果无法确定，使用原身份核对事实再决定重试。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "items": [
      {
        "bot_uid": "bot-1",
        "item_id": "one",
        "status": "unknown"
      }
    ]
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 读取机器人 Webhook 安全设置 {#getBotWebhookSecurity}

`POST /api/v1/bots/webhook-security/get`

读取本人 Webhook Bot 的关键词、token 校验开关及 IP 白名单；不返回接入 token，不适用于 OpenClaw。

Operation ID：`getBotWebhookSecurity`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uid` | `string` | 是 | 本人 Webhook Bot UID。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/webhook-security/get' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"bot_uid":"bot-1"}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uid` | `string` | 是 | 目标 Webhook Bot UID。 |
| `revision` | `integer` | 是 | 当前 Bot 写入水位。 |
| `security` | `object` | 是 | 当前安全设置，不包含接入 token。 |
| `security.keyword_enabled` | `boolean` | 是 | 是否启用 Webhook 关键词校验。 |
| `security.keyword` | `string` | 是 | 完整关键词，关闭时传空字符串。 |
| `security.token_enabled` | `boolean` | 是 | 是否启用既有 Webhook token 校验；工具不会返回 token。 |
| `security.ip_whitelist_enabled` | `boolean` | 是 | 是否启用来源 IP 白名单。 |
| `security.ip_whitelist` | `array<string>` | 是 | 完整白名单，使用既有 Webhook 安全规则支持的 IP 或网段格式。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "bot_uid": "bot-1",
    "revision": 100,
    "security": {
      "ip_whitelist": [],
      "ip_whitelist_enabled": false,
      "keyword": "",
      "keyword_enabled": false,
      "token_enabled": true
    }
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```

### 设置机器人 Webhook 安全规则 {#setBotWebhookSecurity}

`POST /api/v1/bots/webhook-security/set`

读取当前水位后明确提交本人 Webhook Bot 的完整安全设置。此操作不读取或轮换 token，不改变其他 Bot 或 runtime 接入方式。

Operation ID：`setBotWebhookSecurity`

#### 请求字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uid` | `string` | 是 | 本人 Webhook Bot UID。 |
| `expected_revision` | `integer` | 是 | 读取到的当前 Bot 水位。 |
| `security` | `object` | 是 | 明确提交完整安全设置。 |
| `security.keyword_enabled` | `boolean` | 是 | 是否启用 Webhook 关键词校验。 |
| `security.keyword` | `string` | 是 | 完整关键词，关闭时传空字符串。 |
| `security.token_enabled` | `boolean` | 是 | 是否启用既有 Webhook token 校验；工具不会返回 token。 |
| `security.ip_whitelist_enabled` | `boolean` | 是 | 是否启用来源 IP 白名单。 |
| `security.ip_whitelist` | `array<string>` | 是 | 完整白名单，使用既有 Webhook 安全规则支持的 IP 或网段格式。 |

#### 请求示例

```bash
curl -X POST 'https://openapi.jotmo.cc/api/v1/bots/webhook-security/set' \
  -H 'Authorization: Bearer arkme_<key-id>_<secret>' \
  -H 'Content-Type: application/json' \
  -d '{"bot_uid":"bot-1","expected_revision":100,"security":{"keyword_enabled":true,"keyword":"通知","token_enabled":true,"ip_whitelist_enabled":false,"ip_whitelist":[]}}'
```

#### 返回字段

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `bot_uid` | `string` | 是 | 目标 Bot UID。 |
| `status` | `enum<string>` | 是 | succeeded 或 conflict；冲突需重读当前设置。 |

**枚举值说明**

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `status` | `succeeded` | 当前操作已完成；发送请求不表示 Bot 已回答。 |
| `status` | `conflict` | 事实已变化，重读并确认意图。 |

#### 成功响应示例

```json
{
  "code": 200,
  "data": {
    "bot_uid": "bot-1",
    "status": "succeeded"
  },
  "message": "请求成功",
  "request_id": "request-example-1"
}
```
