# Webhook 推送 (https://sellersheetai.com/zh/help/app/settings/webhooks)

> 亚马逊关于你店铺的通知——商品、价格与报价、订单、库存、销售、财务、账户健康等——推送到你的团队聊天群，或以签名 JSON 推送到你自己的系统。





<Callout title="TL;DR">
  * 你的 listing、价格、报价、订单、库存或账户发生变化时，亚马逊会通知 SellerSheet。**Webhook** 把每条消息转发出去：在团队聊天群（飞书 / Lark、Slack、Microsoft Teams、企业微信、钉钉）里显示为卡片，或通过 HTTPS 以签名 JSON 推送到你自己的系统。
  * **可从 23 类亚马逊通知中选择**，按组列出；新建的 Webhook 默认勾选六类。每小时指标和逐条变动的通知只能推送到 HTTPS。
  * 在 **设置 → Webhook 推送 → 添加 Webhook** 中设置（工作区所有者或管理员），然后点击 **发送测试**。
  * **所有套餐每月免费送达 500 条消息。** 超出部分每条送达的消息从积分中扣费。测试、发送失败和未发送的消息从不计费。
</Callout>

## Webhook 能做什么 [#what-for]

你的卖家账户发生变化时，亚马逊会发出通知：listing 被屏蔽或恢复可购买、你的报价因价格失去推荐报价（Featured Offer）资格、有人修改了你品牌的详情页、其他卖家跟卖了你的 ASIN、买家申请取消订单、FBA 库存售罄、你的账户出现风险。Webhook 把这些消息送到你工作的地方：

* **团队聊天群。** 每分钟最多一张卡片，按店铺分组，并附上亚马逊自己的字段名，群里的人——或群里的 AI 智能体——可以直接据此处理。
* **你自己的系统。** ERP、数据库或你自己的代码以签名 JSON 收到每条消息，里面原样带着亚马逊的通知。

每条消息只用亚马逊发来的内容组成；SellerSheet 不会为此另外调用亚马逊接口补充信息。亚马逊是唯一的事实来源。

<img alt="通知如何送达。卖家账户有变化时——Listing、价格与报价、订单、库存、账户健康、报告——亚马逊发出通知。SellerSheet 只向亚马逊订阅你的 Webhook 需要的通知，把一分钟内的变化合成一张群聊卡片，每个 HTTPS 请求都带签名；所有套餐每月 500 条免费。它推送到你的团队群聊——飞书、Slack、Teams、企业微信或钉钉，每分钟最多一张卡片，颜色取最严重的变化——或以带签名的 JSON 推送到你自己的系统，每次最多 100 条消息，内含亚马逊的原始通知。某个通知 24 小时没有 Webhook 需要，SellerSheet 就在亚马逊取消订阅" src="__img0" />

## 添加 Webhook [#add-a-webhook]

你需要是工作区的**所有者或管理员**。Webhook 属于你当前所在的工作区：请先切换到正确的工作区。

<Steps>
  <Step>
    ### 获取地址 [#获取地址]

    按下方[推送目标](#destinations)中对应目标的步骤复制地址。推送到 HTTPS 时，还要自己生成一个签名密钥。
  </Step>

  <Step>
    ### 添加 Webhook [#添加-webhook]

    在 [SellerSheet 应用](https://sellersheetai.com/home)中打开 **设置 → Webhook 推送 → 添加 Webhook**：

    * **推送方式**：飞书、Slack、Microsoft Teams、企业微信、钉钉或 HTTPS。之后不能修改。
    * **Webhook 名称**：在工作区内唯一，例如 *ERP 对接* 或 *运营群*。
    * 地址；目标支持时，填写 **签名密钥**。
    * 仅聊天应用：**语言**——中文或 English，群里卡片使用的语言。新建时默认跟你使用应用的语言，之后随时可以修改。见[卡片语言](#card-language)。
    * **通知与店铺**：哪些通知、哪些店铺。最初的六类通知默认已勾选。见[选择通知与店铺](#types-and-stores)。
    * **包括未连接到 SellerSheet 的站点**（默认打开）。
    * 仅聊天应用：**竞争报价：仅在卖家或购物车赢家变化时推送**（默认打开）。只有价格变化的消息会被过滤——不推送、不计费。
    * 勾选按消息计费的确认框，然后点击 **创建 Webhook**。

    只有当组织能为下一条消息付费时——本月还有免费消息，或有积分——才能创建 Webhook 或重新开启它。
  </Step>

  <Step>
    ### 发送测试 [#发送测试]

    在 Webhook 所在行（或它的编辑面板里）点击 **发送测试**。目标会收到一个虚构店铺的示例消息，这个 Webhook 接收的每类通知各一条；聊天应用里卡片标题以“· 测试”结尾（语言为 English 的 Webhook 是“· test”）。如果目标拒收，页面会显示它的回复——见[常见问题排查](#troubleshooting)。测试消息从不计费。
  </Step>
</Steps>

之后，列表会显示每个 Webhook 的 **推送状态**、**本月消息**（已送达的消息数）和 **最近推送**。**编辑 Webhook** 可以修改除推送方式以外的所有设置；地址或密钥留空则保留原值，**启用推送** 用来开启或关闭这个 Webhook。**删除 Webhook** 会立即停止推送；它的推送记录保留 30 天。每个工作区最多保留 **10 个 Webhook**。

地址和密钥加密保存，之后不会再显示：列表只显示地址的最后四个字符。

### 推送目标 [#destinations]

| 目标              | 收到什么                   | 签名密钥        |
| --------------- | ---------------------- | ----------- |
| 飞书 / Lark       | 每分钟最多一张互动卡片            | 可选——飞书的签名校验 |
| Slack           | 每分钟最多一条消息              | —           |
| Microsoft Teams | 每分钟最多一张 Adaptive Card  | —           |
| 企业微信            | 每分钟最多一条 markdown 消息    | —           |
| 钉钉              | 每分钟最多一条 markdown 消息    | 可选——钉钉的“加签” |
| HTTPS           | 签名 JSON，每个请求最多 100 条消息 | **必填**      |

启用了自定义关键词的聊天机器人需要添加关键词 `SellerSheet`——每张卡片的标题都包含它。设置了 IP 白名单的机器人或接收端点需要放行 SellerSheet 的 IP 地址：请[联系客服](/zh/help/contact)获取。

#### 飞书 / Lark [#feishu]

1. 在群里打开 **设置 → 群机器人 → 添加机器人 → 自定义机器人**。
2. 复制它的 webhook 地址：`https://open.feishu.cn/open-apis/bot/v2/hook/…`（Lark：`https://open.larksuite.com/open-apis/bot/v2/hook/…`）。
3. 可选安全设置：打开**签名校验**并把密钥粘贴到 **签名密钥**，或打开**自定义关键词**并填写关键词 `SellerSheet`。

#### Slack [#slack]

1. 在你的 Slack 应用中打开 **Incoming Webhooks**。
2. 点击 **Add New Webhook** 并选择频道。
3. 复制地址：`https://hooks.slack.com/services/…`

#### Microsoft Teams [#teams]

1. 在频道中打开 **工作流**。
2. 选择 **“收到 webhook 请求时发布到频道”** 并完成工作流设置。
3. 复制工作流给出的地址；它的域名以 `logic.azure.com` 或 `powerplatform.com` 结尾。

#### 企业微信 [#wecom]

1. 在群里打开 **··· → 群机器人 → 添加**。
2. 复制它的 webhook 地址：`https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=…`

企业微信能接收的消息比其他应用短，所以它的卡片在“+N more”之前能显示的行数更少。

#### 钉钉 [#dingtalk]

1. 在群设置中打开 **机器人 → 添加机器人 → 自定义**。
2. 在安全设置中选择 **加签**，把以 `SEC` 开头的密钥粘贴到 **签名密钥**；或选择**自定义关键词** `SellerSheet`。
3. 复制地址：`https://oapi.dingtalk.com/robot/send?access_token=…`

#### HTTPS [#https]

1. 准备一个接收端点：接受带 JSON 请求体的 `POST`，地址是公网可访问的 `https://` 地址（端口 443）。私有和内网地址会被拒绝，也不会跟随重定向。每次请求前都会重新检查地址。
2. 自己生成一个足够长的随机签名密钥（例如 `openssl rand -hex 32` 的输出），粘贴到 **签名密钥**，并在你的接收端保存一份。
3. 在接收端[校验每个请求的签名](#verify-signature)，10 秒内返回任意 `2xx`，然后再处理消息。

收到的内容：[HTTPS 请求体](#https-body)。

## 选择通知与店铺 [#types-and-stores]

**通知与店铺** 表格按组列出亚马逊提供的全部通知：每行一类通知，每列一个店铺。

* 勾选 **所有店铺** 会接收工作区的所有店铺，包括之后连接的店铺；也可以逐个勾选店铺。
* **新建的 Webhook 默认勾选最初的六类通知**——商品问题、商品状态、品牌内容、价格健康、竞争报价和账户健康——并勾选所有店铺；只有品牌内容默认只勾选一个店铺。其他通知按需勾选。
* **灰色的行不能勾选**，并注明原因：*以数据形式进入你的报表，不作为 Webhook 推送*（亚马逊广告）、*暂未开放*（物流追踪节点），或推送到聊天群时的 *仅限 HTTPS*。见[通知类型](#notifications)。
* **高频**：推送到 HTTPS 时，每小时指标和每次变动一条消息的通知带有这个标记。店铺繁忙时每天可能有很多条，每条送达的消息都计入[用量](#pricing)。
* **有些通知只针对部分站点：** FBA Onsite 货件只在巴西发送（*仅限 BR*）。没有巴西站点的店铺不能勾选它。**所有店铺** 始终可以勾选：亚马逊不会为其他店铺发送。
* **每个店铺各一份：** **品牌内容** 和 **商品类型定义**，亚马逊会给同一卖家的每个店铺各发一份，内容相同。只选一个店铺，每次变化只收到一次；选多个就每个店铺各收到一份，表格会提醒你。
* **不涉及具体站点的消息**——账户健康、报告、上传文件、Data Kiosk 查询、多渠道配送订单、自发货库存数量、外部仓发货——会发给在该卖家任一店铺上接收这类通知的 Webhook。
* **聊天群不接收仅限 HTTPS 的通知。** 如果在选择聊天应用之前已勾选了这类通知，表单会提示有几项不会发送；它们也不会保存。
* **包括未连接到 SellerSheet 的站点**：有些通知覆盖你整个卖家账户，所以消息可能涉及你没有连接到 SellerSheet 的站点。打开时，这些消息照常送达，卡片上标注“(not connected)”，HTTPS 中为 `"connected": false`。关闭即可不接收。

### 亚马逊订阅跟随你的 Webhook [#amazon-subscriptions]

SellerSheet 只向亚马逊订阅你的 Webhook 需要的通知，不多订：

* 每个卖家账户、区域和通知类型只有一个亚马逊订阅，供所有 Webhook 共用。新建的 Webhook 如果接收的店铺和通知已经订阅，会立即开始收到消息。
* 还没有任何 Webhook 需要的通知，会在约一分钟内向亚马逊订阅。
* 某个店铺的某类通知连续 24 小时没有任何开启中的 Webhook 需要时，SellerSheet 会在亚马逊取消订阅。之后若有 Webhook 再次需要，会在约一分钟内重新订阅。取消订阅期间亚马逊发布的消息不会送达。
* 店铺单元格上的小标记会说明即将结束的订阅（*亚马逊订阅将于 … 结束，除非有 Webhook 重新接收它。*）或被亚马逊拒绝的订阅：*该卖家的这类通知已被其他应用订阅*；*此通知需要的权限不在该店铺的授权范围内*（SellerSheet 每天重试一次；若一直失败，请重新授权店铺或联系客服）；或 *SellerSheet 会再次尝试*。

## 通知类型 [#notifications]

Webhook 推送页面列出 SellerSheet 能推送的亚马逊 Selling Partner API 通知，以及亚马逊广告的两个 Marketing Stream 数据集，分为 9 组：

* **已上线：23 类通知。** 最初的六类在新建 Webhook 时默认勾选（下表标为“默认”）。
* **暂未开放：物流追踪节点。** 亚马逊要求先逐个登记货件。
* **亚马逊广告：不是 Webhook。** 广告表现以数据形式进入你的报表（Amazon Marketing Stream），所以这两行在任何推送方式下都是灰色的。

推送到聊天群时，仅限 HTTPS 的通知也是灰色的，并注明原因。推送到 HTTPS 时这些行可以勾选，其中每小时指标和每次变动一条消息的通知带有 **高频** 标记。

不提供：亚马逊巴西和墨西哥的三类税务发票通知。亚马逊只允许获得税务开票角色的应用订阅，SellerSheet 的应用没有这个角色。

### 商品与 Listing [#group-listings]

| 通知      | 告诉你什么                                                | 上线      | 推送方式               |
| ------- | ---------------------------------------------------- | ------- | ------------------ |
| 商品问题    | listing 的问题发生变化：当前生效的严重程度和处置动作，或问题已全部清除。从不包含问题的具体文字。 | 已上线（默认） | HTTPS、聊天群          |
| 商品状态    | listing 变为可购买或不可购买、能否被搜索到，或已删除。                      | 已上线（默认） | HTTPS、聊天群          |
| 品牌内容    | 你品牌下某个商品目录条目的属性变化——标题、五点描述、图片等。每个店铺各一份。              | 已上线（默认） | HTTPS、聊天群          |
| 商品类型变更  | 某个 ASIN 的商品类型变了；它的 listing 需要填写的内容可能随之变化。            | 已上线     | HTTPS、聊天群          |
| 自发货库存数量 | 某个 SKU 的自发货库存数量变化。                                   | 已上线     | 仅限 HTTPS：每次变动一条消息  |
| 商品类型定义  | 亚马逊发布某个站点商品类型定义的新版本，并列出新增的商品类型。每个店铺各一份。              | 已上线     | 仅限 HTTPS：供你自己的程序使用 |

### 价格与报价 [#group-pricing]

| 通知    | 告诉你什么                                      | 上线      | 推送方式              |
| ----- | ------------------------------------------ | ------- | ----------------- |
| 价格健康  | 你的报价因价格无法成为推荐报价，附带亚马逊的参考价格。只有 ASIN，没有 SKU。 | 已上线（默认） | HTTPS、聊天群         |
| 竞争报价  | 有其他卖家的在售 ASIN 上报价变化：购物车、价格、卖家。             | 已上线（默认） | HTTPS、聊天群         |
| 企业购报价 | 同上，针对 ASIN 上的企业购（B2B）报价。                   | 已上线     | 仅限 HTTPS：每次变动一条消息 |
| 费用促销  | 亚马逊为你提供费用促销：内容、时间和折扣。                      | 已上线     | HTTPS、聊天群         |

### 订单与配送 [#group-orders]

| 通知                | 告诉你什么                  | 上线   | 推送方式      |
| ----------------- | ---------------------- | ---- | --------- |
| 订单变更              | 订单状态变化，或买家提出变更，例如取消订单。 | 已上线  | HTTPS、聊天群 |
| 多渠道配送订单           | 多渠道配送订单的状态、包裹和物流单号。    | 已上线  | HTTPS、聊天群 |
| FBA Onsite 货件（巴西） | 亚马逊为订单创建或取消货件。*仅限 BR。* | 已上线  | HTTPS、聊天群 |
| 外部仓发货             | 你自己的配送仓里某个货件的状态变化。     | 已上线  | HTTPS、聊天群 |
| 物流追踪节点            | 货件的承运商追踪节点。            | 暂未开放 | HTTPS、聊天群 |

### 库存 [#group-inventory]

| 通知     | 告诉你什么                                      | 上线  | 推送方式              |
| ------ | ------------------------------------------ | --- | ----------------- |
| FBA 库存 | 某个 SKU 的 FBA 库存数量变化——可售、入库中、预留、不可售——按站点列出。 | 已上线 | 仅限 HTTPS：每次变动一条消息 |
| 每小时库存  | 每小时：高可用库存的件数。                              | 已上线 | 仅限 HTTPS：每小时指标    |

### 销售与流量 [#group-sales]

| 通知      | 告诉你什么         | 上线  | 推送方式           |
| ------- | ------------- | --- | -------------- |
| 每小时销售   | 每小时：订购件数和销售额。 | 已上线 | 仅限 HTTPS：每小时指标 |
| 每小时页面浏览 | 每小时：详情页浏览量。   | 已上线 | 仅限 HTTPS：每小时指标 |

### 财务 [#group-finance]

| 通知 | 告诉你什么                        | 上线  | 推送方式              |
| -- | ---------------------------- | --- | ----------------- |
| 交易 | 一笔交易记入你的账户：类型、金额和相关编号，例如订单号。 | 已上线 | 仅限 HTTPS：每次变动一条消息 |

### 账户状况 [#group-account]

| 通知   | 告诉你什么                  | 上线      | 推送方式      |
| ---- | ---------------------- | ------- | --------- |
| 账户健康 | 卖家账户状态在正常、有风险和已停用之间变化。 | 已上线（默认） | HTTPS、聊天群 |

### 报告与数据（开发者） [#group-data]

| 通知              | 告诉你什么                                | 上线  | 推送方式               |
| --------------- | ------------------------------------ | --- | ------------------ |
| 报告完成            | 报告请求处理结束——完成、已取消或失败——附报告 ID 和文档 ID。  | 已上线 | 仅限 HTTPS：供你自己的程序使用 |
| 上传文件处理完成        | 上传文件（feed）处理结束——完成、已取消或失败——附结果文档 ID。 | 已上线 | 仅限 HTTPS：供你自己的程序使用 |
| Data Kiosk 查询完成 | Data Kiosk 查询结束，附数据文档或错误文档 ID。       | 已上线 | 仅限 HTTPS：供你自己的程序使用 |

### 亚马逊广告（Marketing Stream） [#group-ads]

| 数据集       | 内容                         | 推送                     | 方式 |
| --------- | -------------------------- | ---------------------- | -- |
| 广告表现（每小时） | 每小时：各广告活动的曝光、点击、花费、转化和销售额。 | 以数据形式进入你的报表，不是 Webhook | —  |
| 转化商品（每天）  | 每天：看到广告后购买的商品。             | 以数据形式进入你的报表，不是 Webhook | —  |

每条消息的 `summary` 都带一行可读的 `text` 和一个 `severity`，以及该通知自己的字段。每类通知在亚马逊的代码（`messageType`）和字段：[Webhook 消息格式](/zh/help/app/settings/webhooks-schema)。

### 你会看到的情况 [#amazon-behaviour]

* **消息何时到达。** 商品问题和商品状态通常在变化后约 11–19 分钟到达；价格健康和品牌内容约一分钟内到达。默认的六类里，竞争报价通常量最大。
* **删除后的“问题已清除”。** 删除一个 SKU 约 20 分钟后，亚马逊会清除它的问题；这条消息和其他消息一样送达。
* **最后一个竞争者离开。** 只有 ASIN 上有其他卖家时亚马逊才会通知，所以最后一个卖家离开时不会有消息。
* **报告完成也包括 SellerSheet 自己的报告：** 即 SellerSheet 为同步你店铺数据而请求的报告，每天很多个。
* **把消息当作确认。** 你修改 listing、价格或品牌内容后，消息会告诉你亚马逊已经生效。

### 严重程度与颜色 [#severity]

| `severity` | 卡片颜色 | 何时                                                                                                                                    |
| ---------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `critical` | 红色   | listing 被屏蔽或其商品目录条目被移除；账户被停用；订单无法配送                                                                                                   |
| `warning`  | 橙色   | 其他 listing 问题；listing 不可购买或已删除；商品类型变更；价格健康；其他卖家拿到了购物车；账户有风险；缺货（自发货或 FBA）；买家申请取消或订单已取消；配送订单部分完成或已取消；货件已取消；报告、上传文件或 Data Kiosk 查询被取消或失败 |
| `info`     | 蓝色   | 其他情况——例如品牌内容、你持有购物车或无人持有时的竞争报价、每小时指标、交易、费用促销、已完成的报告                                                                                   |
| `recovery` | 绿色   | 问题已清除；listing 恢复可购买；账户恢复正常；多渠道配送订单完成                                                                                                  |

## 聊天卡片显示什么 [#chat-card]

<Figures>
  <Figure src="/assets/images/blog/sellersheet-webhooks/feishu-channel.webp" width="2000" height="1355" alt="名为 Amazon alerts 的飞书群里，群机器人发来的五张 SellerSheet Webhooks 卡片，从早到晚：红色——listing 被屏蔽、不可购买；橙色——价格健康和买家申请取消订单；橙色——其他卖家拿到购物车；蓝色——品牌内容有修改；绿色——listing 恢复可购买、问题已清除" caption="飞书 / Lark · 点击放大" />

  <Figure src="/assets/images/blog/sellersheet-webhooks/slack-channel.webp" width="2000" height="1650" alt="同样五张卡片在 Slack 频道 #amazon-alerts 中：每张有加粗标题，彩色侧边条内是店铺的各行内容和页脚" caption="Slack · 点击放大" />
</Figures>

语言选 **中文** 的 Webhook，卡片是这样的（上面两张图里是语言选 English 的卡片）：

```text
SellerSheet Webhooks · myStore · 3 条消息
myStore-US (3)
• 商品问题 · SKU SKU-EXAMPLE-01 · B0EXAMPLE01 — 商品不可购买（被禁止显示） · Severities=ERROR · EnforcementActions=LISTING_SUPPRESSED
• 商品状态 · SKU SKU-EXAMPLE-02 · B0EXAMPLE02 — 可购买 · Status=BUYABLE,DISCOVERABLE
• 竞争报价 · B0EXAMPLE05 — 1 个其他卖家：A2EXAMPLEOTHER 19.99 USD FBM，购物车，好评率 95%（120 条） · 你 21.49 USD FBA，好评率 99%（812 条） · OfferChangeType=External · BuyBoxPrice=19.99 USD · NumberOfOffers=new Merchant 1,new Amazon 1
亚马逊 02:28 发送（02:14 变更）GMT-7 · 各项含义
```

* **每分钟最多一张卡片。** 第一条消息开启一个一分钟的窗口；窗口内到达的所有消息都放在同一张卡片上。（窗口累计到 2,000 条消息时会立即发出卡片。）
* **标题：** `SellerSheet Webhooks`、店铺名称（最多两个，否则显示店铺数）和消息数。
* **颜色：** 取卡片上最严重的[严重程度](#severity)。
* **分组：** 每个店铺 ref 一组，例如 `myStore-US`；“（未连接）”标注你没有连接的站点（English 卡片上是“(not connected)”）。
* **每一行：** 通知类型、SKU 和 ASIN（ASIN 链接到该站点的商品页），通俗说明，然后是亚马逊自己的字段名和值，格式为 `Field=VALUE`，群里的 AI 智能体可以直接依据这些代码处理。竞争卖家的 ID 链接到它的店铺页，店铺页上能看到名称；最多列出 5 个卖家，之后显示“另 N 个”。
* **重复：** 相同的消息——同一店铺、通知类型、文字和变化时间——合并为一行，以 `×N` 结尾。每一条都已送达，也都计数。
* **长卡片：** 超过 40 行或聊天应用的大小上限后，卡片以“另有 N 条 — 查看推送记录”结尾，链接到这个 Webhook 的[推送记录](#delivery-log)。卡片承载的每条消息，无论是否显示，都已送达。
* **底部：** 亚马逊发出消息的时间，括号里是变化发生的时间（若是更早的一天则带日期），按第一个店铺所在站点的时区；然后是 **各项含义**，链接到本节说明。

### 卡片语言 [#card-language]

每个聊天类 Webhook 都有 **语言**：中文或 English。SellerSheet 写在卡片上的字都跟着它——消息数、通知类型名、通俗说明、“（未连接）”、“另有 N 条”和底部；中文卡片底部的 **各项含义** 打开本节的中文版。亚马逊自己的字段名和值（`Severities=ERROR`、`competitivePriceThreshold=24.99 USD`）、SKU、ASIN、卖家 ID 和价格保持亚马逊发来的原样，所以群里的 AI 智能体无论卡片是哪种语言，读到的都是同一套代码。

HTTPS 没有语言选项：JSON 里原样带着亚马逊的通知。

## HTTPS 请求体 [#https-body]

每个请求都是 `POST`，`Content-Type: application/json`，并带以下请求头：

| 请求头                         | 值                                                               |
| --------------------------- | --------------------------------------------------------------- |
| `X-SellerSheet-Webhook-Id`  | Webhook 的 ID                                                    |
| `X-SellerSheet-Delivery-Id` | 这次推送的 ID——每次重试都相同                                               |
| `X-SellerSheet-Timestamp`   | 这次尝试发出时的 Unix 秒数                                                |
| `X-SellerSheet-Signature`   | `sha256=` 加上以你的签名密钥为 key、对“时间戳、一个 `.`、原始请求体”计算的十六进制 HMAC-SHA256 |
| `X-SellerSheet-Test`        | **发送测试** 时为 `true`，否则为 `false`                                  |

请求体是一次**推送**（delivery）：最多 100 条消息，不超过 1 MB。积累到 100 条消息，或第一条消息到达 2 秒后，就会发出请求。下面是包含一条消息的示例，数值均为虚构：

```json
{
  "deliveryId": "dlv_8f3a1c9e2b7d4e6fa0b1c2d3e4f5a6b7",
  "webhookId": "0c6f2a8e-4d1b-4e7a-9b35-6e8d2f1a4c90",
  "organizationId": "7b2e9c41-0d3a-4f6b-8e15-9c2a4d6f8b30",
  "sentAt": "2026-10-27T09:28:33Z",
  "attempt": 1,
  "schemaVersion": 1,
  "messages": [
    {
      "messageId": "5c0e8f4a-2b7d-4e91-a3c6-000000000001",
      "messageType": "LISTINGS_ITEM_ISSUES_CHANGE",
      "fingerprint": "sha256:af6e358a51bec4bc1275fba29469312dce87aa4609a42c42564a35c8c190d1a5",
      "store": {
        "storeId": "3f6c2a9e-5b1d-4c8e-9a7f-2d4e6b8c0a11",
        "ref": "myStore-US",
        "sellerId": "A1EXAMPLESELLER",
        "marketplaceId": "ATVPDKIKX0DER",
        "countryCode": "US",
        "connected": true
      },
      "eventTime": "2026-10-27T09:14:03Z",
      "publishTime": "2026-10-27T09:28:30Z",
      "receivedAt": "2026-10-27T09:28:32Z",
      "summary": {
        "text": "SKU SKU-EXAMPLE-01 (B0EXAMPLE01) on US: Listing not buyable (suppressed) · Severities=ERROR · EnforcementActions=LISTING_SUPPRESSED",
        "severity": "critical",
        "sku": "SKU-EXAMPLE-01",
        "asin": "B0EXAMPLE01",
        "severities": ["ERROR"],
        "enforcementActions": ["LISTING_SUPPRESSED"],
        "cleared": false
      },
      "amazon": {
        "notificationType": "LISTINGS_ITEM_ISSUES_CHANGE",
        "notificationVersion": "1.0",
        "payloadVersion": "2023-12-13",
        "eventTime": "2026-10-27T09:14:03.000Z",
        "notificationMetadata": {
          "ApplicationId": "amzn1.sp.solution.00000000-0000-4000-8000-000000000000",
          "SubscriptionId": "9d4b7e2a-6c1f-4a85-b3e0-000000000001",
          "PublishTime": "2026-10-27T09:28:30.000Z",
          "NotificationId": "5c0e8f4a-2b7d-4e91-a3c6-000000000001"
        },
        "payload": {
          "Sku": "SKU-EXAMPLE-01",
          "Asin": "B0EXAMPLE01",
          "SellerId": "A1EXAMPLESELLER",
          "MarketplaceId": "ATVPDKIKX0DER",
          "Severities": ["ERROR"],
          "EnforcementActions": ["LISTING_SUPPRESSED"]
        }
      }
    }
  ]
}
```

怎么读：

* **推送本身。** `deliveryId` 在同一请求的每次重试中都相同；`attempt` 是第几次尝试（1 到 3）。`webhookId` 和 `organizationId` 分别是 Webhook 和你的工作区。`schemaVersion` 为 `1`。
* **`messageId`** 是亚马逊的 NotificationId：一条亚马逊消息。**`messageType`** 是亚马逊的通知类型。`schemaVersion` 1 内可能新增类型：遇到不认识的类型，按它的 `summary.text` 处理，或直接跳过。
* **`fingerprint`** 对亚马逊再次发布的同一变化保持相同——见[重复消息](#duplicates)。
* **`store`** 是你的店铺和这条消息涉及的站点：`ref` 是店铺 ref（`myStore-US`）；对于你没有连接的站点，`connected` 为 `false`。
* **时间**均为 UTC：`eventTime` 是变化发生的时间，`publishTime` 是亚马逊发出的时间，`receivedAt` 是 SellerSheet 收到的时间。
* **`summary`** 是 SellerSheet 的解读：一行可读的 `text`、[`severity`](#severity)、`sku`、`asin`，以及该通知类型自己的字段。
* **`amazon`** 是亚马逊的通知，每个值都与亚马逊发送的完全一致——这是事实来源。亚马逊有些通知的键用 PascalCase，有些用 camelCase：两种写法都要能读。
* 每个键都会发送；没有值的键为 `null`。对象不封闭：遇到不认识的键直接忽略。

请求体的 JSON Schema（2020-12）发布在 [sellersheetai.com/schemas/webhooks-v1.json](https://sellersheetai.com/schemas/webhooks-v1.json)，每类通知的示例推送在 [sellersheetai.com/schemas/webhooks-v1-samples.json](https://sellersheetai.com/schemas/webhooks-v1-samples.json)。所有字段、类型和示例：[Webhook 消息格式](/zh/help/app/settings/webhooks-schema)。

**发送测试** 的请求带 `X-SellerSheet-Test: true`，以及虚构店铺 `SampleStore` 的示例消息，这个 Webhook 接收的每类通知各一条。像其他请求一样回复它，但不要据此执行任何操作。

## 校验签名 [#verify-signature]

信任一个请求之前先校验它：

1. 读取**原始**请求体字节，在任何 JSON 解析之前。
2. 时间戳与你的时钟相差超过 5 分钟就拒绝——被重放的请求会失败。每次重试都带新的时间戳，所以重试能通过。
3. 以签名密钥为 key，对 `时间戳 + "." + 原始请求体` 计算 HMAC-SHA256，用常量时间比较 `sha256=<hex>` 与请求头。
4. 校验通过就立即返回 `2xx`，之后再处理消息；校验失败返回 `401`。

```python title="verify.py"
import hashlib, hmac, time

def verify(secret: str, headers, raw_body: bytes, tolerance: int = 300) -> bool:
    timestamp = headers.get("X-SellerSheet-Timestamp", "")
    signature = headers.get("X-SellerSheet-Signature", "")
    if not timestamp.isdigit() or abs(time.time() - int(timestamp)) > tolerance:
        return False
    mac = hmac.new(secret.encode(), timestamp.encode() + b"." + raw_body, hashlib.sha256)
    return hmac.compare_digest("sha256=" + mac.hexdigest(), signature)
```

```js title="verify.mjs"
import { createHmac, timingSafeEqual } from "node:crypto";

// headers: lower-case names, as Node gives them; rawBody: a Buffer of the body as received
export function verify(secret, headers, rawBody, tolerance = 300) {
  const timestamp = headers["x-sellersheet-timestamp"] ?? "";
  const signature = headers["x-sellersheet-signature"] ?? "";
  if (!/^\d+$/.test(timestamp) || Math.abs(Date.now() / 1000 - Number(timestamp)) > tolerance) return false;
  const mac = createHmac("sha256", secret).update(`${timestamp}.`).update(rawBody).digest("hex");
  const expected = Buffer.from(`sha256=${mac}`);
  const given = Buffer.from(signature);
  return expected.length === given.length && timingSafeEqual(expected, given);
}
```

在 Express 中，用 `express.raw({ type: "application/json" })` 读取该路由的原始请求体；在 Flask 中用 `request.get_data()`。

## 重试、暂停与恢复 [#retries-and-pause]

* **重试。** 每次推送立即尝试一次，20 秒后和 90 秒后各再试一次——`deliveryId` 不变，`attempt` 递增。每次尝试最多等待 10 秒回复。
* **什么算尝试失败：** 回复不是 `2xx`（包括重定向——不会跟随），10 秒内没有回复，连接不上，或聊天应用在回复中表示拒收（例如飞书的 `code`、企业微信的 `errcode`）。
* **推送失败。** 三次尝试都失败时，这次推送的消息记为 **发送失败**：不计费，也不会再发送。
* **暂停。** **连续 3 次推送失败**后，Webhook 变为 **已暂停（连续失败）**，组织的所有者和管理员会收到一封邮件。中间只要有一次送达，计数就重新开始。
* **恢复。** Webhook 推送页面会为暂停的 Webhook 显示一条横幅。**恢复推送** 会先发送一条测试消息，目标接受后才重新开启；否则保持暂停，并显示目标的回复。
* **暂停或关闭期间**，不发送也不计费。期间到达的消息在推送记录中记为 **未发送**，之后也不会补发。
* **已暂停（积分不足）。** 见[计费与用量](#pricing)：它会自动恢复。
* **太慢。** 如果某个 HTTPS 接收端点积压了 2,000 条消息，发给它的新消息会立即记为失败（“the webhook answers too slowly”），而不会拖慢其他 Webhook。
* 要自己停止一个 Webhook，编辑它并取消勾选 **启用推送**。

## 重复消息与 messageId [#duplicates]

亚马逊是事实来源：SellerSheet 送达亚马逊发出的每一条消息，包括亚马逊自己的重复发送，中途不丢弃任何消息。

* **重试会重复一次推送。** 如果你的接收端已经处理了某次推送但回复太晚，下一次尝试会带来相同的 `deliveryId` 和相同的消息。把处理过的 `messageId` 保留一两天，遇到已有的就丢弃。
* **亚马逊有时会把同一变化再发布一次**，作为一条新消息——新的 `messageId`，相同的 `eventTime`。它的 `fingerprint` 相同，所以如果每个变化只想处理一次，就比较 `fingerprint`。在聊天卡片上，这类重复合并为一行 `×N`。
* **品牌内容** 和 **商品类型定义**：你勾选的每个店铺各收到一份——只勾选一个店铺，每次变化只收到一次。
* **竞争报价**走 HTTPS 时每条都会送达，`sellersChanged` 和 `buyBoxWinnerChanged` 说明与上一条消息相比，ASIN 上的卖家或购物车赢家是否变化；只想要这些变化时，按这两个字段过滤。

## 计费与用量 [#pricing]

* **每月免费送达 500 条消息**，每个组织、所有套餐都一样。每月 1 日（UTC）重新计数。
* **超出 500 条后**，每条送达的消息从组织的积分中扣费，价格显示在 Webhook 推送页面上。套餐与积分：[套餐与价格](/zh#pricing)和[账单与积分](/zh/help/app/settings/billing)。
* **一条消息送达一个 Webhook 计为一条。** 被两个 Webhook 接收的消息计两次。聊天卡片承载的每条消息都计数，包括 `×N` 合并的行和“+N more”。
* **从不计费：** 测试消息、发送失败的消息、未发送的消息（Webhook 暂停或关闭时）和已过滤的消息（聊天 Webhook 的竞争报价选项）。
* **80 %。** 本月消息达到 400 条时，所有者会收到一封邮件。
* **积分用完。** 本月 500 条用完且积分耗尽时，组织的 Webhook 会暂停（**已暂停（积分不足）**），所有者会收到一封邮件。充值后或下个月开始时，它们会自动恢复。余额归零后，大约还会有一分钟的消息送达；余额不会变成负数。
* **在哪里查看：** Webhook 推送页面顶部显示本月消息数、500 条中剩余的数量和本月 Webhook 花费的积分；**账单与积分** 的积分卡片显示同样的内容；[积分明细](/zh/help/app/settings/billing#ledger)中每次扣费一行；推送记录显示每次推送的计费消息数。

## 推送记录 [#delivery-log]

**设置 → Webhook 推送 → 推送记录** 列出最近 30 天的每次推送和每条消息，最新的在前。可以从 Webhook 推送页面顶部的按钮打开，也可以从某个 Webhook 所在行打开（**查看它的推送记录**，已按该 Webhook 筛选），或点击聊天卡片上的“+N more”链接。

**查看** 在两个列表之间切换：

| 列表       | 每行是                | 列                                                                                                                      |
| -------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| **推送批次** | 一个 HTTPS 请求或一张聊天卡片 | **发送时间**、**Webhook**（名称和推送方式）、**结果**（测试推送带 **测试** 标签）、**发送消息数**、**计费消息数**（扣费后显示“已计费”）、**HTTP 状态码**、**尝试次数**、**错误信息**   |
| **消息**   | 一条亚马逊消息            | **接收时间**、**通知类型**、**所属店铺**（不涉及你的店铺时显示“不是 SellerSheet 中的店铺”）、**SKU / ASIN**、**推送结果**（它在每个 Webhook 的结果，或“没有 Webhook 接收”） |

筛选条件保存在页面地址中，筛选后的视图可以收藏或分享：

* 两个列表都有 **Webhook** 和 **时间范围**（**最近 1 小时**、**最近 24 小时**、**最近 7 天**、**最近 30 天**）。
* **结果**：推送批次为 **已送达** 或 **发送失败**；消息另有 **未发送** 和 **已过滤**。
* 仅消息列表：**通知类型**、**所属店铺**，以及 **搜索 SKU 或 ASIN**——完整的 SKU，或 ASIN。
* **重置** 清除筛选。**列** 按钮用来显示或隐藏列。

| 结果       | 含义                                                       |
| -------- | -------------------------------------------------------- |
| **已送达**  | 目标接受了它。超出本月免费 500 条后计费。                                  |
| **发送失败** | 每次尝试都失败，或这个 Webhook 积压太多。不计费，也不会再发送。                     |
| **未发送**  | 消息到达时 Webhook 处于暂停或关闭状态。不计费，之后也不补发。                      |
| **已过滤**  | 聊天 Webhook 开启了 **竞争报价：仅在卖家或购物车赢家变化时推送**，而这条消息只有价格变化。不计费。 |

在某条消息上点 **查看详情**，会显示它的 **消息 ID**、**接收时间**、**事件时间**、**所属店铺**、**SKU / ASIN**、**消息指纹**、它在每个 Webhook 的结果，以及 **推送的消息内容**——与送达时完全一致的消息 JSON，可点 **复制 JSON**。JSON 在消息到达几分钟后才可查看（在此之前面板会提示稍后再打开），保留 30 天。

## 常见问题排查 [#troubleshooting]

**发送测试**、推送记录的 **错误信息** 列和暂停横幅会显示目标自己的回复：

| 你看到的                                       | 处理                                               |
| ------------------------------------------ | ------------------------------------------------ |
| Feishu 19021                               | 签名校验失败：按飞书显示的原样重新粘贴密钥——如果机器人没有开启签名校验，就删除密钥。      |
| Feishu 19022                               | 机器人设置了 IP 白名单：[联系客服](/zh/help/contact)获取需放行的 IP。 |
| Feishu 19024                               | 关键词校验失败：添加关键词 `SellerSheet`。                     |
| DingTalk 310000                            | 安全设置拒收：检查关键词 `SellerSheet`、加签密钥或 IP 设置。          |
| DingTalk 300001 · WeCom 93000              | 机器人地址已失效：重新复制地址。                                 |
| DingTalk 130101 · WeCom 45009              | 触发了应用的频率限制：多个 Webhook 推送到同一个群。把它们合并成一个。          |
| Slack: invalid_token, no_service           | Slack webhook 已被删除：新建一个。                         |
| Teams: …                                   | 工作流拒收：在 Teams 中检查该工作流。                           |
| HTTP 3xx (redirects are not followed)      | 使用最终地址。                                          |
| 接收端返回 HTTP 401 / 403                       | 你的签名校验拒绝了请求：基于原始请求体、用 Webhook 上保存的密钥校验。          |
| no answer within 10 s                      | 先返回 `2xx`，之后再处理。                                 |
| could not connect                          | 接收端已停止，或无法从公网访问。                                 |
| That address is not on the public internet | 使用公网 `https://` 地址，端口 443。                       |

**Webhook 收不到任何消息：**

* 它的状态是 **推送中**——没有暂停或关闭。
* 在拥有该店铺的工作区里，勾选了你要的通知和店铺。
* 如果变化发生在你没有连接的站点，**包括未连接到 SellerSheet 的站点** 需要打开。
* 在推送记录的 **消息** 列表里，可以看到消息是否到达，以及它在每个 Webhook 的结果（**未发送**、**已过滤**、“没有 Webhook 接收”）。
* 编辑面板中店铺单元格上的标记会说明亚马逊拒绝了订阅。若标记指出店铺授权缺少某项权限，请在[店铺与市场](/zh/help/app/settings/stores)重新授权该店铺；仍然失败请[联系客服](/zh/help/contact)。

## 常见问题 [#faq]

### 谁可以管理 Webhook？ [#谁可以管理-webhook]

工作区的所有者或管理员。成员看不到 Webhook 推送页面。

### 一个工作区可以有几个 Webhook？ [#一个工作区可以有几个-webhook]

最多 10 个。

### 为什么有些通知不能勾选？ [#为什么有些通知不能勾选]

灰色的行是这个 Webhook 无法接收的通知：亚马逊广告（以数据形式进入你的报表，不作为 Webhook 推送）或物流追踪节点（暂未开放），或推送到聊天群时仅限 HTTPS 的——每小时指标、每次变动一条消息，或供你自己的程序使用。行上会注明原因。

### Webhook 怎么收费？ [#webhook-怎么收费]

每个组织每月免费送达 500 条消息，所有套餐都一样。超出部分每条送达的消息从组织的积分中扣费，价格显示在 Webhook 推送页面上。测试、发送失败、未发送和已过滤的消息从不计费。

### Webhook 能发邮件吗？ [#webhook-能发邮件吗]

不能。邮件不是推送目标，请使用聊天群或 HTTPS 接收端点。SellerSheet 仍会用邮件发送自己的通知：Webhook 因连续推送失败而暂停时发给所有者和管理员；本月免费消息用到 80 % 和积分用完时发给所有者。

### Webhook 会读取我的 Google 表格吗？ [#webhook-会读取我的-google-表格吗]

不会。Webhook 只转发亚马逊的通知；SellerSheet 推送时不读写你的表格。

### SellerSheet 店铺提醒去哪了？ [#sellersheet-店铺提醒去哪了]

店铺提醒现在就是 Webhook 推送。同样的通知和聊天应用，另有 17 类亚马逊通知，所有套餐可用，每个工作区最多 10 个，还能用 HTTPS 推送到你自己的系统。
