# General Translation Platform: Webhooks
URL: https://generaltranslation.com/zh/docs/platform/dashboard/reference/webhooks.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 配置 Webhook 端点、验证签名，并处理来自 General Translation 的翻译事件。Webhook 参考。

Webhooks 会以带签名的 HTTP POST 请求将翻译事件发送到你的后端。你可以在文件或作业发生变更时，用它来触发自己的工作流。

*注意：Webhook 需要 Team 或 Enterprise 方案。*

## 创建 Webhook [#create-webhook]

1. 前往 **Organization &gt; Developer &gt; Webhooks**。
2. 点击 **Add endpoint**。
3. 输入要接收事件的端点 URL。该 URL 必须使用 HTTPS。
4. 选择要订阅的事件类型。
5. 点击 **Create endpoint**。

创建端点后，打开 Webhook 详情页并复制签名密钥。使用此密钥验证传入请求是否来自 General Translation。

每个 Organization 最多可创建 **5 个 Webhook 端点**。

## 事件类型 [#event-types]

每个端点都可以订阅一个或多个事件类型。你可以在 Webhook 详情页更新订阅。

* `translated_file.completed` 会在翻译后的文件生成完成并可供下载时触发。
* `translated_file.edited` 会在用户在 Translation Editor 中手动编辑翻译后的文件时触发。
* `translation_job.completed` 会在翻译任务完成时触发。

## Payload 格式 [#payload-format]

每次 webhook 投递都会通过 HTTP POST 发送一个 JSON 请求体：

```json
{
  "id": "evt_xxx",
  "type": "translated_file.completed",
  "created_at": "2026-04-30T12:00:00.000Z",
  "api_version": "2026-03-06.v1",
  "data": {
    "object": {
      "id": "file_xxx",
      "org_id": "org_xxx",
      "project_id": "project_xxx",
      "branch_id": "branch_xxx",
      "source_file_id": "src_xxx",
      "file_id": "file_xxx",
      "version_id": "ver_xxx",
      "locale": "fr",
      "file_format": "json",
      "data_format": null,
      "completed_at": "2026-04-30T12:00:00.000Z"
    }
  }
}
```

顶层 `id` 是一个稳定的事件标识符，可用于对重复投递进行去重。

## 验证签名 [#verify-signatures]

每个 Webhook 请求都包含三个请求头：

* `webhook-id` 是事件 ID，例如 `evt_xxx`。
* `webhook-timestamp` 是请求发送时的 Unix 时间戳，单位为秒。
* `webhook-signature` 是 `v1,<base64-hmac>` 签名。

该签名遵循 [Standard Webhooks](https://www.standardwebhooks.com/) 规范。

要验证请求，请按以下步骤操作：

1. 将 `{webhook-id}.{webhook-timestamp}.{raw request body}` 拼接起来。
2. 去掉密钥中的 `whsec_` 前缀后，对其进行 Base64 解码以获取签名密钥。
3. 使用解码后的签名密钥，对拼接后的字符串计算 HMAC-SHA256。
4. 将结果进行 Base64 编码。
5. 将其与 `v1,` 前缀之后的签名值进行比较。
6. 检查时间戳是否与当前时间相差不超过 5 分钟，以防止重放攻击。

### 示例：Node.js

```js
import crypto from "crypto";

function verifyWebhook(payload, headers, secret) {
  const msgId = headers["webhook-id"];
  const timestamp = headers["webhook-timestamp"];
  const signature = headers["webhook-signature"];

  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - parseInt(timestamp)) > 300) {
    throw new Error("Timestamp too old");
  }

  const signingKey = Buffer.from(secret.replace("whsec_", ""), "base64");
  const signedContent = `${msgId}.${timestamp}.${payload}`;
  const expected = crypto
    .createHmac("sha256", signingKey)
    .update(signedContent)
    .digest("base64");

  const received = signature.split(",")[1];
  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
    throw new Error("Invalid signature");
  }

  return JSON.parse(payload);
}
```

你也可以使用适用于你的编程语言的 [Standard Webhooks](https://www.standardwebhooks.com/) 库，它会自动处理验证。

## 处理重试与投递 [#handle-retries-delivery]

Webhook 使用 **至少一次投递**。

如果你的端点未在 10 秒内返回 `2xx` 响应，系统会以指数退避方式重试此次投递，最多重试 **10 次**。

你可以在仪表板的 **Organization &gt; Developer &gt; Webhook 事件** 中手动重试失败的投递。在列表中选择该事件，然后将鼠标悬停在 **投递尝试** 下的某一行上并点击 **Retry**。

展开某次失败的尝试以查看其 **错误** 字段。对于非 `2xx` 响应，错误信息会包含 HTTP 状态码，并且可能包含端点响应请求体的脱敏摘录。General Translation 会从响应中最多读取 4,096 字节，并最多存储 500 个字符用于诊断。

## 查看事件和投递尝试 [#view-events]

1. 前往 **Organization &gt; Developer &gt; Webhook 事件**。
2. 从 Organization 中触发的事件列表中选择一个事件。
3. 查看该事件的**投递尝试**。

每次尝试都会显示状态、端点 URL 和时间戳。展开已有记录结果的尝试，可查看其为**自动**还是**手动**、往返延迟，以及连接错误或超时等传输失败的**错误**摘要。尚未记录结果的待处理尝试无法展开。

自动重试会显示为**自动**投递。从仪表板发起的重试会显示为**手动**。

## 处理重复事件 [#handle-duplicate-events]

由于事件投递至少会发生一次，你的端点可能会多次收到同一事件。请使用请求体中的 `id` 字段进行去重。

```js
app.post("/webhooks/gt", (req, res) => {
  const eventId = req.body.id;

  if (alreadyProcessed(eventId)) {
    return res.status(200).send("OK");
  }

  // 处理事件...
  markProcessed(eventId);
  res.status(200).send("OK");
});
```

## 管理端点 [#manage-endpoints]

在 **Organization &gt; Developer &gt; Webhooks** 中，您可以：

* 在不删除端点的情况下启用或禁用它
* 更新已订阅的事件类型
* 查看签名密钥
* 删除端点

在 **Organization &gt; Developer &gt; Webhook 事件** 中，您可以查看投递历史、查看单次投递尝试的详情，以及重试失败的投递。

## 最佳实践 [#best-practices]

* 尽快返回 `2xx` 响应，然后异步处理事件。
* 在信任请求体之前，先验证 `webhook-signature` 请求头。
* 存储已处理事件的 ID，并跳过重复事件。
* 生产环境中的 Webhook 端点应使用 HTTPS。
* 在 **Webhooks &gt; Events** 中监控持续发生的投递故障。

## 权限 [#permissions]

管理 Webhook 端点和重试投递需要 `org:webhooks:write` 权限。

查看事件和投递尝试需要 `org:webhooks:read` 权限。

默认情况下，**Admin** 和 **Developer** 角色同时具有这两项权限。 (详情请参阅[角色和权限](/docs/platform/dashboard/reference/roles-and-permissions)) 。

## Sitemap

See the full [sitemap](https://generaltranslation.com/sitemap.md) for all pages.
