V4 Webhook

什么是 Webhook?

Webhook 是一种推送式 HTTP 回调,当您的帐户中发生特定事件时(例如,新文件完成转码、添加了评论、创建了项目),Frame.io 会立即触发该回调。

您无需轮询 API,只需提供一个公共 HTTPS URL;Frame.io 会实时向该 URL 发送 JSON 负载,以便您能够:

将元数据同步到外部 DAM/MAM
填充 Slack 频道或票证系统

有关 Webhook 的更多信息及其功能,请参见 https://docs.webhook.site/。

端点概述

操作端点详细信息
创建 WebhookPOST /v4/accounts/{account_id}/workspaces/{workspace_id}/webhooks请求体包含 nameurlevents[]
列出工作区的所有 WebhookGET /v4/accounts/{account_id}/workspaces/{workspace_id}/webhooks支持分页
显示一个 WebhookGET /v4/webhooks/{webhook_id}仅在创建时返回签名密钥
更新 WebhookPATCH /v4/webhooks/{webhook_id}更改 urleventsis_active
删除 WebhookDELETE /v4/webhooks/{webhook_id}立即停止传递

身份验证 — 所有 V4 端点都需要通过 Adobe Developer Console 获取的 OAuth 2.0 访问令牌。 接受旧版开发者令牌和 JWT。

Frame V4 中的更改和更新

在旧版中创建的 Webhook 转移到 V4 时,发生了以下更改:

  1. 负载结构:在负载中添加帐户 ID
  2. 端点更改:JSON 负载中不再提供 team_id,而是在 URL 的路径参数中:https://api.frame.io/v4/accounts/:account_id/workspaces/:workspace_id/webhooks
  3. API 集成:由于 API 结构、端点和身份验证方法有变化,任何用于接收 Webhook 和后续调用 Frame.io API 以实现资源丰富和查找的现有代码都需要更新
  4. 事件类型:资产 Webhook 已拆分为单独的文件事件和文件夹事件,任何来自旧版且具有资产事件的 Webhook 都需要更新为具有相应的文件事件和文件夹事件

迁移后的 Webhook 状态:当您的帐户迁移到 Frame.io V4 时,先前版本的现有 Webhook 会自动停用。 这可以确保您能够修改 Webhook 端点和集成逻辑来适应 V4 的更新,然后再重新激活它们。 未针对 V4 兼容性更新的 Webhook 如果在没有正确修改的情况下启用,将会遇到错误。 您可以通过 API 检查 is_active 字段,或在重新打开之前查看您的 Webhook 设置来验证哪些 Webhook 处于非活动状态。

Webhook 事件订阅

在创建和更新 Webhook 时,请确定您感兴趣的事件。 您可以根据需要选择订阅的事件数量,但请注意,订阅的事件越少,体验就会越好。您可以根据不同的命名方案和不同的端点,按照逻辑拆分您的 Webhook,以便在接收端对业务逻辑进行建模,从而减少共享函数中的筛选和路由操作。

事件范围 — 所有事件的范围都限定在创建 Webhook 时提供的工作区内。 这意味着对于该工作区中所有项目中执行的操作都会发送事件。

项目

事件描述
project.created已创建一个新项目
project.updated已更新某个项目的设置
project.deleted已删除一个项目

文件

事件描述
file.created已在 Frame.io 中创建了一个文件。 *注意:*这会在文件上传完成之前触发。 如果您的处理程序需要完整文件,建议改为监听 upload.completed 事件
file.ready在文件上传并处理完毕后,所有转码均已完成
file.updated文件的名称或其他信息已更改
file.deleted文件已被删除(手动删除或其他方式)
file.upload.completed上传一个文件
file.versioned创建一个文件版本

文件夹

事件描述
folder.created已创建一个新文件夹
folder.updated已更新一项文件夹的设置
folder.deleted已删除一个文件夹

评论

事件描述
comment.created已创建一条新的评论或回复
comment.updated已更新一条评论
comment.deleted已删除一条评论
comment.completed一条评论已被标记为已完成
comment.uncompleted一条评论已被标记为未完成

元数据

事件描述
metadata.value.updated资产的元数据字段已更新

收藏集

事件描述
collection.created已创建一个新收藏集
collection.updated已更新收藏集
collection.deleted已删除收藏集

自定义字段

事件描述
customfield.created已创建一个新的自定义字段
customfield.updated已更新一个自定义字段
customfield.deleted已删除一个自定义字段

共享

事件描述
share.created已创建一个新共享项
share.updated已更新一个共享项
share.deleted已删除一个共享项
share.viewed已查看一个共享项

Webhook 消息负载

所有 Webhook 负载都包含一个 type 字段,用于指示发生的事件,以及一个 resource 对象。 resource 对象包含与该事件相关的 Frame.io 资源的 typeID

示例负载

1{
2 "account": {
3 "id": "6f70f1bd-7e89-4a7e-b4d3-7e576585a181"
4 },
5 "project": {
6 "id": "7e46e495-4444-4555-8649-bee4d391a997"
7 },
8 "resource": {
9 "id": "d3075547-4e64-45f0-ad12-d075660eddd2",
10 "type": "file"
11 },
12 "type": "file.ready",
13 "user": {
14 "id": "56556a3f-859f-4b38-b6c6-e8625b5da8a5"
15 },
16 "workspace": {
17 "id": "378fcbf7-6f88-4224-8139-6a743ed940b2"
18 }
19}

在上文中的 file.created 事件示例中,resource.id 指示了新创建文件的 ID。 此外,还包含 workspaceprojectuser 对象,这些对象包含相关的 workspace.idproject.iduser.id。 这些值可用于通过筛选传入事件或在本地查找缓存数据来减少 API 调用。

我们没有包含除资源 ID 之外的关于订阅资源的任何其他信息

如果您的应用程序需要其他信息或上下文,我们建议进行 API 调用来查找有关所参考资源的更多信息。

安全性

默认情况下,所有 Webhook 都有一个签名密钥。 这个不可配置的签名密钥可用于验证请求是否源自 Frame.io。

您配置的 Webhook 的响应负载包括特定于该 Webhook 的签名密钥。 此密钥仅在初始 Webhook 创建响应中提供,因此请将其存储在密钥存储或环境变量中的安全位置。 稍后将其用来验证 Webhook 是否直接来自我们的服务器,且未被拦截或以任何方式篡改。

验证 Webhook 签名

为了保护集成免受中间人攻击和重放攻击,验证 Webhook 负载的签名至关重要。 验证可确保 Webhook 负载确实由 Frame.io 发送,并且负载内容在传输过程中未被修改。

POST 请求中包含以下 HTTP 标头:

标头名称描述示例
X-Frameio-Request-Timestamp发送请求的时间戳1604004499
X-Frameio-Signature计算 Webhook 签名v0=a77ce6856e609c884575c2fd211d07a9ad1c3f72e19c06ff710e8f086ffca883
user-agent: "Frame.io V4 API"v4 标头中的用户代理
user-agent: "Frame.io Legacy API"旧版标头中的用户代理
Python
1import hmac
2import hashlib
3
4def verify_signature(curr_time, req_time, signature, body, secret):
5 """
6 Verify Webhook signature
7 :Args:
8 curr_time (float): Current epoch time
9 req_time (float): Request epoch time
10 signature (str): Signature provided by the Frame.io API for the given request
11 body (str): Webhook body from the received POST
12 secret (str): The secret for this Webhook that you saved when you first created it
13 """
14 if int(curr_time) - int(req_time) < 500:
15 message = 'v0:{}:{}'.format(req_time, body)
16 calculated_signature = 'v0={}'.format(hmac.new(
17 bytes(secret, 'latin-1'),
18 msg=bytes(message, 'latin-1'),
19 digestmod=hashlib.sha256).hexdigest())
20 if calculated_signature == signature:
21 return True
22 return False

时间戳是 Frame.io 系统发送出站 Webhook 时的系统时间。 这可以用于防止重放攻击。 我们建议验证此时间与本地时间相差是否在 5 分钟以内。 签名是使用首次创建 Webhook 时提供的签名密钥的 HMAC SHA256 哈希值。 按照以下步骤验证签名:

1

提取签名

从 HTTP 标头中提取签名。

2

创建要签名的消息

通过合并版本、交付时间和请求体 :v0:timestamp:body 来创建一个用于签名的消息。

3

计算 HMAC SHA256

使用您的签名密钥计算 HMAC SHA256 签名。

4

比较签名

将您计算的签名与提供的签名进行比较!

提供的签名以 v0= 为前缀。 目前 Frame.io 只有这一种用于请求签名的版本。 请务必将此前缀附加到您计算出的签名之前。

重试和记录

重试策略
  • 共计五次尝试(初始 + 4 次重试)

  • 从 15 秒开始的指数退避(+ 抖动)

  • 2xx 状态或超过 5 秒超时会触发重试

故障记录

Frame.io 会保留一份故障日志,其中包含:webhook_idaccount_idevent_typeresource_iduser_id

Webhook 教程

步骤 1:设置接收端(首先完成此步骤,以便您知道 URL 是什么)

在这里,我们使用 webhook.site,它允许您轻松启动一个一次性 Webhook 接收器,该接收器可用于检查负载、发送基础响应,无需任何实际的商业逻辑。 当您首次导航到 https://webhook.site 时,系统会为您创建一个独特的 Webhook 端点,您可以立即复制使用。

此 URL 是您本次会话特有的。

步骤 1 示例

步骤 2:选择您要订阅的事件

在本教程中,我们将保持简单,设置此 Webhook 来仅订阅 file.created 事件。 我们用于创建 Webhook 的 JSON 负载如下。

1{
2 "data": {
3 "name": "asset.created sample webhook",
4 "events": ["file.created"],
5 "url": "https://webhook.site/c05f2216-9558-4816-bc09-f77ee7b9de40"
6 }
7}

步骤 3:使用 Postman 创建 Webhook 资源

使用 Postman,发出 API 调用以创建 Webhook 资源,在负载中提供 webhook.site 端点。

步骤 4:测试!

现在您已经创建了 Webhook 订阅且设置了接收 Webhook 的端点,是时候通过执行适当的操作来触发第一个 Webhook 进行测试了!

由于我们的示例已设置为在 file.created 触发器上触发,我们将继续向设置 Webhook 的相应帐户和工作区内的任何项目中上传新资产。

步骤 4 示例

其他资源