跳至内容
文档

出站 Webhook:载荷与签名

通过任意 HTTPS 端点接收带签名的 JSON 格式 AutoPSEO 告警和报告:包括请求头、请求体字段、事件类型以及签名验证方法。

账户 → Slack、Teams 与 Webhooks → 出站 Webhooks需要订阅或试用阅读需 2 分钟

出站 Webhook 会把 AutoPSEO 的告警、定时报告、测试消息和报告摘要发送到你自己运行的端点,每条消息对应一个使用 HMAC-SHA256 签名的 JSON POST 请求。你可以用它对接 Zapier、Make、n8n、故障管理工具或你自己的代码,无需 Slack 或 Teams 账号。想了解把文章投递到你网站的 Webhook?那属于内容引擎的功能,请参阅内容投递。

添加 Webhook

  1. 在出站 Webhook 区域,点击新建 Webhook。
  2. 为它设置名称,并粘贴端点的 URL。该 URL 必须是公网 HTTPS 地址:普通 http、localhost、以 .local 或 .internal 结尾的名称、不含点号的主机名,以及私有或链路本地 IP 地址都会被拒绝。
  3. 复制保存后显示的签名密钥。该密钥只会显示这一次。
  4. 点击发送测试以推送一条 test 事件,然后将定时报告或告警关联到该 Webhook。

Webhook 请求的格式

每条消息都是带有以下请求头的 POST 请求:

请求头值
Content-Typeapplication/json
User-AgentAutoPSEO-Webhook/1.0
X-AutoPSEO-Event事件类型,例如 traffic_drop
X-AutoPSEO-Signaturesha256= 后接 64 位小写十六进制字符

下面是 2026 年 10 月 12 日 06:00 UTC 运行时针对某个域名资源产生的流量下降告警,已格式化以便阅读(实际传输时为紧凑的 JSON,其中的 id 和 site_id 为虚构值):

{
  "id": "9b2e61f04c3a4d7e8f15a0b6c2d39e47",
  "event_type": "traffic_drop",
  "severity": "high",
  "site_id": "4f0c1e9a2b7d4c58",
  "site_url": "sc-domain:example.com",
  "occurred_at": "2026-10-12T06:00:04.183Z",
  "title": "Traffic drop: example.com",
  "text": "Clicks 1,500 vs 2,000 in the previous window (-25.0%).",
  "url": "https://app.autopseo.com/property/sc-domain%3Aexample.com",
  "payload": {
    "fields": [
      { "label": "Metric", "value": "clicks" },
      { "label": "Current", "value": "1,500" },
      { "label": "Baseline", "value": "2,000" },
      { "label": "Window", "value": "7 days (2026-10-05 → 2026-10-11 vs 2026-09-28 → 2026-10-04)" },
      { "label": "Change", "value": "-25.0%" }
    ],
    "table": null,
    "detector": "traffic_drop",
    "window": 7,
    "range": { "start": "2026-10-05", "end": "2026-10-11", "compStart": "2026-09-28", "compEnd": "2026-10-04" },
    "result": {
      "fired": true,
      "metric": "clicks",
      "value": 1500,
      "baseline": 2000,
      "change": -0.25,
      "severity": "high",
      "summary": "Clicks 1,500 vs 2,000 in the previous window (-25.0%)."
    }
  },
  "source": "autopseo"
}

以下顶层字段对所有事件都相同:

字段含义
id随机生成的 32 位十六进制字符串,每次请求都不同
event_type发生的事件(见下一节)
severity告警为 critical、high、medium 或 low;报告、摘要和测试为 info
site_idAutoPSEO 中该资源的 id;测试和演示资源为 null
site_urlSearch Console 资源,例如 sc-domain:example.com 或 https://www.example.com/;测试时为 null
occurred_at消息生成的时间,采用 UTC 的 ISO 8601 时间戳
title、textSlack 和 Teams 中显示的标题与摘要句
urlAutoPSEO 中对应的报告;测试时为 null
payload.fields带标签的值,Slack 中显示为字段,Teams 中显示为事实项
payload.table报告和摘要的 columns 与 rows,其他情况为 null
source始终为 autopseo

比率均以小数表示:change 为 -0.25 表示下降 25%,ctr 为 0.034 表示 3.4%。

事件类型

event_type发送时机payload 中的额外键
traffic_drop、traffic_spike、position_drop、ctr_drop、new_lost_rankings、anomaly、index_flip、rank_drop、audit_regression告警规则触发时,按计划触发或通过测试规则触发detector、window、range(日期;index_flip、rank_drop 和 audit_regression 为 null)、result
scheduled_report定时报告发出时,按计划发送或通过立即发送发送reportType(summary、queries、pages 或 rankings)、range(日期加 label)、totals、previous
report_summary有人在报告页面使用发送到 Slack 时无:数据位于 fields 和 table 中
test有人在该 Webhook 上点击发送测试时sample,始终为 true

result 复述检测器的测量结果:fired、metric、value、baseline、change(无可比较对象时为 null)、severity 和 summary;anomaly 还会包含 z,即修正 z 分数。totals 和 previous 包含报告两个时间窗口的 clicks、impressions、ctr 和 position。各检测器的测量内容请参阅告警。

如何验证签名

签名是对 AutoPSEO 发送的原始字节计算的 HMAC-SHA256,以 Webhook 的签名密钥作为密钥,格式为 sha256= 加小写十六进制。验证步骤如下:

  1. 在进行任何 JSON 解析之前先读取原始请求体。解析后再序列化可能会改变字节内容。
  2. 对这些字节计算 HMAC-SHA256,密钥按文本使用:即所显示的 64 位字符串原样使用,不要按十六进制解码。
  3. 加上前缀 sha256=,并以恒定时间比较的方式将结果与 X-AutoPSEO-Signature 请求头对比。
  4. 两者不一致时拒绝该请求。否则立即返回 2xx 状态码,耗时的处理放到之后再做。

一个无需依赖的 Node.js 接收端示例:

import { createServer } from 'node:http';
import { createHmac, timingSafeEqual } from 'node:crypto';

const secret = process.env.AUTOPSEO_WEBHOOK_SECRET;

createServer((req, res) => {
  const chunks = [];
  req.on('data', (chunk) => chunks.push(chunk));
  req.on('end', () => {
    const raw = Buffer.concat(chunks);
    const expected = Buffer.from('sha256=' + createHmac('sha256', secret).update(raw).digest('hex'));
    const received = Buffer.from(String(req.headers['x-autopseo-signature'] || ''));
    if (received.length !== expected.length || !timingSafeEqual(received, expected)) {
      res.writeHead(401).end();
      return;
    }
    res.writeHead(204).end();
    const event = JSON.parse(raw.toString('utf8'));
    console.log(event.event_type, event.severity, event.site_url);
  });
}).listen(8080);

长度检查必须放在前面,因为当两个缓冲区长度不同时,Node 的 timingSafeEqual 会抛出异常。

投递规则

  • 每条消息只尝试一次,超时时间为 10 秒。任何非 2xx 的响应都视为失败,并连同状态码和你的响应体开头部分一起记录在投递历史中。
  • 不会跟随重定向。3xx 响应会失败,并提示改用最终 URL。
  • 不会按计时器重试。发送失败的告警不会被标记为已发送,因此下次检查时会重新评估,若仍然触发则再次推送:大多数检测器为次日早晨,索引状态翻转(index flip)为下一小时。发送失败的定时报告在同一周期内不会重发,请在修复端点后使用立即发送。
  • id 是按请求生成的,因此它标识的是一次投递而不是一个事件。若要对告警去重,请组合使用 event_type、site_url 和 occurred_at 的日期:除非有人运行测试规则,否则一条规则对每个资源每个 UTC 日最多推送一次。

签名密钥

AutoPSEO 只在你保存 Webhook 时显示一次签名密钥,之后列表中不再显示。请立即将它与接收端的配置一起保存,并与它所保护的端点放在一起。

URL 本身以加密方式存储,列表中只显示其主机名和末尾几个字符。删除 Webhook 的同时也会删除所有向它推送的规则。如果想在 Teams 频道中看到可读的卡片而不是 JSON,请使用 Microsoft Teams。

让你的 SEO 内容自动运行

连接 Search Console 和你的网站,AutoPSEO 会立即扫描并规划首批主题。无需信用卡。