🎁 100 free AI Toolkit licenses – apply by August 15.Learn more

注入内容 REST API

要在服务器端注入内容到文档中,请使用本文档中描述的 PATCH 端点。此功能支持版本历史记录、跟踪更改以及通过此端点添加的内容。

更新文档的端点还允许 JSON 更新以修改您在协作服务器上的文档,包括本地部署和云端:

  • 在任何文档服务器端添加 jsonbinarybase64 内容。
  • 使用 UniqueID 扩展 向特定节点注入内容。
  • 用户仍然可以实时协作,因为内容在注入过程中。
  • 跟踪用户和注入内容的更改,完全兼容 快照

用例

内容注入 REST API 可以实现一些方便但复杂的用例:

  • 文档内容的实时翻译。
  • 在服务器端以编程方式标记或操作文档内容。
  • 集成服务器端组件,例如执行 SQL 查询并显示结果。
  • 版本历史集成和无冲突的并发编辑合并。

创建文档

要在 Tiptap Collab 服务器上初始化新文档,请使用 POST 方法和以下端点:

POST /api/documents/:identifier?format=:format

服务器将为成功创建返回 HTTP 状态码 204,如果文档已存在则返回 409(必须先删除才能覆盖),如果操作失败则返回 422

format 参数接受与更新端点相同的值(binarybase64json)。

更新文档

要在协作服务器上更新现有文档,您可以使用 PATCH 方法和以下 API 端点:

PATCH /api/documents/:identifier?format=:format

此端点接受 Yjs 更新消息并将其应用到指定文档。

查询参数

参数类型默认值描述
formatstring更新的格式:jsonbinary(Yjs 的 Y.encodeStateAsUpdate),或 base64(以 Base64 编码的二进制状态)。
modestringdefault更新策略:default 合并节点,append 仅追加,node 用负载替换匹配的节点,attrs 替换匹配节点的属性,delete 删除匹配的节点(无需负载)。参见 模式
nodeAttributeNamestring将更新限制为具有此名称属性的节点。与 nodeAttributeValue 结合使用。
nodeAttributeValuestring将更新限制为具有此值属性的节点。与 nodeAttributeName 结合使用。您可以传递多个值:?nodeAttributeValue=a&nodeAttributeValue=b
checksumstring仅当文档当前状态与此校验和匹配时才应用更新(在获取文档响应中作为 x-FRAGMENTNAME-checksum 返回)。否则返回 409 Checksum mismatch
userstring与此次更改关联的用户 ID。
skipVersioning1如果传递此参数,此次更改不会触发自动版本控制。
upsert0 | 10当为 1 时,如果文档尚不存在,则创建文档,而不是返回 404
fragmentstringdefault要更新的 Yjs 片段。通过传递多个值,可以用相同内容更新多个片段(当 format=json 时):?fragment=a&fragment=b
multi0 | 10仅与 format=json 一起使用。当为 1 时,请求体是一个以片段名为键的 JSON 对象,可在单个请求中用不同内容更新多个片段。仅与默认模式兼容。参见 使用不同内容更新多个片段
mergeAttributes0 | 10仅与 mode=attrs 一起使用。当为 1 时,请求负载中未包含的属性将被保留。当为 0(默认)时,缺失的属性将被删除。
multiUpdatestrue仅与 mode=attrsformat=json 一起使用。允许在单个请求中更新多个具有不同属性值的节点。请求体必须是一个包含 { where, attrs } 对象的 JSON 数组。参见 多重更新

更新成功后,服务器将返回 HTTP 状态 204。如果文档不存在,则返回 404(除非传递了 upsert=1,此时会创建文档);如果负载无效或无法应用更新,则返回 422

示例: 更新文档的 curl 命令

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/DOCUMENT_NAME' \\
--header 'Authorization: Bearer YOUR_JWT' \\
--data '@yjsUpdate.binary'

通过 JSON 更新

通过 JSON 更新时,服务器计算当前文档状态与提供的 JSON 之间的差异,然后内部计算所需的 Yjs 更新以达到目标状态。

为了确保精确更新,尤其是针对特定节点的更改,建议使用 nodeAttributeNamenodeAttributeValue 参数。这些参数可以由 Tiptap 的 UniqueID Extension 或自定义实现生成。 请注意,这仅在使用 mode=default 时适用于顶层节点。

省略这些参数可能会导致覆盖在获取文档和发出更新调用之间所做的任何更新。get document 调用返回一个头 x-${fragmentName}-checksum,可以通过将其传递给更新调用作为 ?checksum=${checksum} 来检测冲突。如果自上次获取以来文档已被更新,更新将以 409 Checksum mismatch. 状态失败。

模式

mode 参数控制内容如何应用到文档:

默认模式

将负载中的节点合并到文档中。这是未指定模式时的默认行为。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "合并的内容" }]
    }
  ]
}'

追加模式

将节点追加到文档的 JSON 表示中,而不更改现有节点。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=append' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "该段落将追加到末尾" }]
    }
  ]
}'

节点模式

将匹配 nodeAttributeName/nodeAttributeValue 的节点替换为负载中的节点。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=node&nodeAttributeName=id&nodeAttributeValue=abc-123' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "type": "paragraph",
  "attrs": { "id": "abc-123" },
  "content": [{ "type": "text", "text": "这将替换整个匹配的节点" }]
}'

属性模式

将匹配节点的所有属性替换为请求负载(仅发送属性对象)。有关 mergeAttributes 的详细信息,请参阅仅更新节点属性

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=attrs&nodeAttributeName=id&nodeAttributeValue=abc-123' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "textAlign": "center",
  "indent": 2
}'

删除模式

删除匹配 nodeAttributeName/nodeAttributeValue 的节点。不需要负载。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=delete&nodeAttributeName=id&nodeAttributeValue=abc-123' \
--header 'Authorization: Bearer YOUR_JWT'

有用的参数组合

跟踪谁做了更改

将用户 ID 与注入的内容关联,用于审计跟踪和版本历史。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&user=bot-user-1' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "由机器人注入" }]
    }
  ]
}'

跳过自动版本控制

注入内容而不创建新的版本快照。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&skipVersioning=1' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "静默更新" }]
    }
  ]
}'

更新特定片段

定位特定的 Yjs 片段而不是默认片段,或同时更新多个片段。

# 更新单个片段
curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&fragment=sidebar' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "侧边栏内容" }]
    }
  ]
}'
# 使用相同内容更新多个片段
curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&fragment=header&fragment=footer' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "共享内容" }]
    }
  ]
}'

使用不同内容更新多个片段

要在单个请求中使用不同内容更新多个片段,请传入 multi=1(配合 format=json),并发送一个以片段名称为键的 JSON 对象。每个值都是该片段完整的 Tiptap JSON 内容,并使用默认模式合并到对应片段中。

?fragment=a&fragment=b(将相同的载荷应用到每个列出的片段)不同,multi=1 允许你为每个片段发送不同内容。

multi=1 仅适用于默认模式。它不能与 modenodeAttributeName/nodeAttributeValuechecksummultiUpdates 组合使用——否则会返回 400。它可以与 userskipVersioningupsert 组合使用。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&multi=1' \
--header 'Authorization: YOUR_SECRET' \
--header 'Content-Type: application/json' \
--data '{
  "default": {
    "type": "doc",
    "content": [
      { "type": "paragraph", "content": [{ "type": "text", "text": "片段 default 中的文本" }] }
    ]
  },
  "otherFragment": {
    "type": "doc",
    "content": [
      { "type": "paragraph", "content": [{ "type": "text", "text": "片段 otherFragment 中的文本" }] }
    ]
  }
}'

使用校验和进行冲突安全更新

仅当自上次获取以来文档未更改时才应用更新。

# 1. 获取文档并记录校验和头(x-default-checksum)。当使用 ?format=json 获取文档时,该头存在。如果您想获取不同片段的校验和,请发送 &fragment=customfragmentname
# 2. 在更新调用中使用该校验和
curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&checksum=THE_CHECKSUM_VALUE' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [{ "type": "text", "text": "仅在文档未更改时应用" }]
    }
  ]
}'

合并属性而不删除现有属性

更新匹配节点上的特定属性,同时保留所有其他现有属性。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=attrs&nodeAttributeName=id&nodeAttributeValue=abc-123&mergeAttributes=1' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "textAlign": "center"
}'

完整示例

示例: 使用 JSON 更新文档

// 定义文档名称、密钥和应用程序 ID
const docName = '' // 如有必要,请进行 URI 编码
const secret = ''
const appId = ''; // 来自 Cloud 仪表板的文档服务器 ID;

// 构建基本 URL
const url = `https://${appId}.collab.tiptap.cloud`

// 获取当前文档的 JSON 表示
const docJson = await axios.get(`${url}/api/documents/${docName}?format=json`, {
    headers: {
    Authorization: secret
  },
})

// 提取文档的 JSON 内容
const tiptapJson = docJson.data
const nodes = tiptapJson.content

// 使用唯一标识符查找并记录特定节点
const query = nodes.find(n => n.attrs?.identifier === 'fe5c0789-85d9-4877-a2c3-bccf5d874866').content[0].text
const resultTable = nodes.find(n => n.attrs?.identifier === '246368b6-0746-4ca1-a16f-8d964aff4041')

console.log(`查询:${query}`)
console.log(JSON.stringify(resultTable.content))

// 向结果表节点附加新内容
resultTable.content.push({
  // 新表行内容在此
  {
    "type": "tableRow",
    "content": [
      {
        "type": "tableCell",
        "attrs": {
          "colspan": 1,
          "rowspan": 1
        },
        "content": [
          {
            "type": "paragraph",
            "attrs": {
              "textAlign": "left"
            },
            "content": [
              {
                "type": "text",
                "text": "Jan"
              }
            ]
          }
        ]
      },
      {
        "type": "tableCell",
        "attrs": {
          "colspan": 1,
          "rowspan": 1
        },
        "content": [
          {
            "type": "paragraph",
            "attrs": {
              "textAlign": "left"
            },
            "content": [
              {
                "type": "text",
                "text": "Thurau"
              }
            ]
          }
        ]
      },
      {
        "type": "tableCell",
        "attrs": {
          "colspan": 1,
          "rowspan": 1
        },
        "content": [
          {
            "type": "paragraph",
            "attrs": {
              "textAlign": "left"
            },
            "content": [
              {
                "type": "text",
                "text": "jan@janthurau.de"
              }
            ]
          }
        ]
      }
    ]
  }
})

// 将更新后的 JSON 发送回服务器以应用更改
await axios.patch(`${url}/api/documents/${docName}?format=json`, tiptapJson, {
  headers: {
    Authorization: secret
  }
})

仅更新节点属性

If you only want to update a node’s attributes, you can use the ?mode=attrs query parameter. This will update only the node’s attributes, not its content. In this mode, the nodeAttributeName and nodeAttributeValue parameters apply to any node, not just top-level nodes.

By default, all attributes on matching nodes are replaced—attributes not included in the payload will be deleted. To preserve existing attributes and update only the attributes specified in the payload, pass ?mergeAttributes=1.

Omitting the node filter (nodeAttributeName, nodeAttributeValue) will result in all nodes being updated.

curl --location --request PATCH '/api/documents/:identifier?format=json&nodeAttributeName=id&nodeAttributeValue=12&mode=attrs' \
--data '{
  "indent": 12,
  "textAlign": "right"
}'

多重更新

当使用 mode=attrs 时,您可以通过传递 multiUpdates=true 在单个请求中更新具有不同属性值的多个节点。您不是在查询参数中使用 nodeAttributeName/nodeAttributeValue 来定位节点,而是在请求体中提供一个更新对象数组。每个对象指定一个 where 子句来匹配节点以及要应用的 attrs

where 子句中的所有条件使用 AND 逻辑连接——节点必须匹配每个指定的属性才能被更新。

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=attrs&multiUpdates=true' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '[
  {
    "where": {
      "id": "id123"
    },
    "attrs": {
      "textAlign": "center"
    }
  },
  {
    "where": {
      "name": "customname"
    },
    "attrs": {
      "indent": 2
    }
  }
]'

您可以将 multiUpdates 与其他参数如 userskipVersioningfragmentmergeAttributes 结合使用:

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc?format=json&mode=attrs&multiUpdates=true&user=bot-user-1&mergeAttributes=1' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '[
  {
    "where": {
      "id": "node-1",
      "type": "heading"
    },
    "attrs": {
      "level": 2
    }
  },
  {
    "where": {
      "id": "node-2"
    },
    "attrs": {
      "textAlign": "right"
    }
  }
]'

文档字段

这些端点允许您读取和更新文档上的自定义 Yjs 字段。当您使用自定义 Yjs 类型(例如 Y.getMap('configuration'))并希望通过 API 获取或更新值时,这非常有用。

获取文档字段

GET /api/documents/:identifier/fields?field=:field&type=:type

返回自定义 Yjs 字段的当前值。

查询参数

参数类型默认值描述
fieldstring自定义字段的名称。
typestring自定义字段的 Yjs 类型。支持的值:maparray。传递错误的类型将返回不正确的结果。注意,调用此端点将在文档上创建该类型(如果它不存在)。为相同的字段名称切换类型将产生意外的副作用。
curl --location 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc/fields?field=configuration&type=map' \
--header 'Authorization: Bearer YOUR_JWT'

更新文档字段

PATCH /api/documents/:identifier/fields?field=:field&type=:type
PUT /api/documents/:identifier/fields?field=:field&type=:type

更新文档上的自定义 Yjs 字段。

  • PATCH 将请求体合并到现有字段值中 —— 仅更新您发送的键,保留现有键。
  • PUT 完全替换字段 —— 请求体中不存在的键将被删除。

查询参数

参数类型默认值描述
fieldstring自定义字段的名称。
typestring自定义字段的 Yjs 类型。目前仅支持 map 类型进行更新。
userstring要与更改关联的用户 ID。
skipVersioning1如果传入,此更改不会触发自动版本控制。

示例:使用 PATCH 合并值

curl --location --request PATCH 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc/fields?field=configuration&type=map' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "key": "newValue",
  "array": [1, 2, 3],
  "object": {
    "id": 62,
    "position": ""
  },
  "arrayOfObjects": [
    { "id": 61 }
  ]
}'

示例:使用 PUT 替换所有值

curl --location --request PUT 'https://YOUR_APP_ID.collab.tiptap.cloud/api/documents/my-doc/fields?field=configuration&type=map' \
--header 'Authorization: Bearer YOUR_JWT' \
--header 'Content-Type: application/json' \
--data '{
  "key": "newValue"
}'

任何未包含在 PUT 请求体中的现有键都将从字段中删除。