Webhook 让 ColdSend 能在你的工作区发生任何变化时实时通知你自己的应用——邮件发出、潜客回复、链接被点击、潜客退订,等等。你不需要轮询 API:事件发生的那一刻,ColdSend 就会向你的端点发送一个 HTTP POST 请求。
本指南带你来创建 Webhook、选择要接收的事件、验证请求确实来自 ColdSend,以及排查投递失败的问题。
适用场景
如果你符合以下情况,就该用 Webhook:
- 想在事情发生的那一刻,把潜客/回复数据同步进 CRM 或内部工具
- 需要触发自动化(例如潜客回复时通知 Slack、潜客退订时更新表格)
- 想实时追踪互动(打开、点击、退信),而不用轮询
- 正在 ColdSend 的营销引擎之上构建自定义集成
前置条件
- 一个能访问 Settings → Webhooks 的 ColdSend 账户
- 一个可公网访问、能接收 POST 请求的 HTTPS 端点(不接受纯
http://地址) - 你的端点必须在 10 秒内返回
2xx状态码,投递才算成功
💡 提示: 还没准备好端点?在搭建集成期间,可以用 webhook.site 或 RequestBin 这类服务来查看 ColdSend 发来的请求。
第 1 步:打开 Webhooks 设置
- 登录你的 ColdSend 账户。
- 在左侧边栏进入 Settings。
- 选择 Webhooks 标签页。
你会看到现有 Webhook 的列表(如果有的话),以及每个 Webhook 的状态和最近一次投递结果。

第 2 步:创建 Webhook
点击 Create Webhook 按钮。
在对话框中填写:
字段 说明 Name 这个 Webhook 的易读名称(例如 “CRM Sync”) Endpoint URL ColdSend 向你 POST 事件的 HTTPS 地址 Event Types 这个 Webhook 要接收哪些事件 选择一个或多个事件类型,或者用 Select All Events 订阅全部。

- 点击 Create Webhook。
可用的事件类型
| 事件 | 触发时机 |
|---|---|
| Reply Received | 潜客回复了邮件 |
| Email Bounced | 邮件退信 |
| Lead Unsubscribed | 潜客退订 |
| Email Sent | 邮件成功发出 |
| Email Delivered | 投递已确认 |
| Email Opened | 邮件被打开 |
| Link Clicked | 邮件中的链接被点击 |
| Lead Status Changed | 潜客状态发生变化 |
第 3 步:保存签名密钥
Webhook 创建完成后,ColdSend 会仅显示一次你的签名密钥:

⚠️ 重要
签名密钥只会显示一次,之后无法再次获取。请立即复制并安全保存(例如放进环境变量或密钥管理服务)。你需要用它来验证收到的请求确实来自 ColdSend(见第 5 步)。
如果你弄丢了密钥,删除这个 Webhook 再新建一个,就能拿到新的密钥。
第 4 步:发送测试事件
在接入集成之前,先验证你的端点能正常工作:
- 在列表中找到你的 Webhook,点击 Test 操作。
- ColdSend 会向你的端点发送一个
ping事件。 - 结果会显示你的端点返回的 HTTP 状态码。

测试事件长这样:
{
"event_type": "ping",
"event_id": "a1b2c3d4-...",
"occurred_at": "2026-08-09T10:00:00+00:00",
"team_id": "your-team-id",
"campaign_id": null,
"data": { "message": "Webhook test from ColdSend" }
}
你的端点应返回任意 2xx 状态(例如 200 OK)。其他任何状态都会被记为失败。
第 5 步:校验请求签名
每个 Webhook 请求都带有 HMAC-SHA256 签名,你可以据此确认请求来自 ColdSend,且没有被篡改。
请求头
| 请求头 | 说明 |
|---|---|
X-ColdSend-Signature |
sha256= 加上原始请求体的 HMAC-SHA256 十六进制摘要 |
X-ColdSend-Event |
事件类型(例如 reply_received) |
X-ColdSend-Delivery-Id |
本次投递的唯一 ID |
X-ColdSend-Attempt |
这是第几次投递尝试(1 = 首次尝试) |
User-Agent |
固定为 ColdSend-Webhooks/1 |
校验步骤
- 以字节形式读取原始请求体(不要解析后再重新序列化 JSON——格式差异会导致签名校验失败)。
- 使用第 3 步的密钥计算
HMAC-SHA256(body, signing_secret)。 - 用恒定时间比较把结果与
X-ColdSend-Signature请求头对比。
Node.js 示例:
import crypto from "crypto";
function verifyColdSendSignature(req, secret) {
const signature = req.headers["x-coldsend-signature"];
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(req.rawBody).digest("hex");
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
Python(FastAPI)示例:
import hashlib
import hmac
def verify_coldsend_signature(body: bytes, secret: str, signature: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode("utf-8"), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
⚠️ 签名不匹配的请求一律拒绝——它不是来自 ColdSend。
第 6 步:处理收到的事件
所有真实事件共用同一个信封结构:
{
"event_type": "reply_received",
"event_id": "7f3a9c1e-...",
"occurred_at": "2026-08-09T10:15:32+00:00",
"team_id": "your-team-id",
"campaign_id": "campaign-id-or-null",
"data": { ... }
}
data 对象随事件类型不同而不同:
| 事件类型 | data 字段 |
|---|---|
email_sent |
lead_email、from_email、subject、sequence_step、message_id |
email_delivered |
lead_email、delivered_at |
email_opened |
lead_email、sequence_step、opened_at |
link_clicked |
lead_email、link_index、url、clicked_at |
email_bounced |
lead_email、bounce_type、status_message、sequence_step |
reply_received |
lead_email、subject、reply_text、is_auto_reply、inbox_email |
lead_unsubscribed |
lead_email、method |
lead_status_changed |
lead_email、from_status、to_status |
reply_received 载荷示例:
{
"event_type": "reply_received",
"event_id": "7f3a9c1e-...",
"occurred_at": "2026-08-09T10:15:32+00:00",
"team_id": "your-team-id",
"campaign_id": "e9d8c7b6-...",
"data": {
"lead_email": "prospect@example.com",
"subject": "Re: Quick question",
"reply_text": "Sure, let's talk Thursday.",
"is_auto_reply": false,
"inbox_email": "alex@yourdomain.com"
}
}
端点的最佳实践
- 快速响应:立即返回
200,再异步处理事件(例如推入队列)。耗时超过 10 秒的请求会被视为失败。 - 保证幂等:ColdSend 保证至少一次投递,所以同一事件偶尔可能到达两次。用
event_id去重。 - 只在成功时返回
2xx:任何2xx都算投递成功;其他一律视为失败。
第 7 步:监控投递
每个 Webhook 都保留一份投递日志,可以在 Webhooks 设置页面查看:
- 点击某个 Webhook,打开它的投递历史。
- 每条记录显示事件类型、状态、HTTP 响应码以及错误信息。

投递状态
| 状态 | 含义 |
|---|---|
| Succeeded | 你的端点返回了 2xx 响应 |
| Failed | 投递失败——要么是 4xx 响应(永久失败,不重试),要么是可重试的失败仍在进行中 |
| Dead | 所有重试尝试都已用尽 |
失败的投递可以在你修好端点后,从投递日志中手动重新投递。
重试与自动暂停
ColdSend 会用指数退避自动重试失败的投递:
| 尝试次数 | 时间 |
|---|---|
| 第 1 次 | 事件发生时立即 |
| 第 2 次 | 约 1 分钟后 |
| 第 3 次 | 约 5 分钟后 |
| 第 4 次 | 约 30 分钟后 |
重试行为取决于失败类型:
- 超时、网络错误和
5xx响应 → 会重试(最多共 4 次尝试) 4xx响应 → 视为永久失败,不重试(先修复客户端的问题,再重新投递)
如果某个 Webhook 出现连续 5 次投递死亡,ColdSend 会自动暂停它,避免持续冲击一个已经坏掉的端点。你随时可以在 Webhooks 设置页面重新启用被暂停的 Webhook。
管理 Webhook
在 Webhooks 设置页面,你可以:
- 编辑 —— 修改名称、端点 URL 或订阅的事件类型
- 暂停 / 恢复 —— 启用或停用某个 Webhook,而不用删除它
- 删除 —— 永久移除某个 Webhook(其签名密钥同时失效)

注意: 被暂停或删除的 Webhook 不会收到任何事件。暂停期间发生的事件,在恢复后不会补发。
故障排查
我的端点始终收不到事件
- 确认该 Webhook 在 Webhooks 设置页面中处于启用状态(未被暂停)
- 确认该 Webhook 订阅了你期望的事件类型
- 确保你的端点可从公网访问——ColdSend 无法访问
localhost、私有 IP 或仅限 VPN 的主机 - 检查投递日志里的错误详情
投递结果显示“Request timed out”
你的端点响应时间超过了 10 秒。请立即返回 200,再异步处理载荷。
签名校验一直失败
- 使用原始请求体的字节——重新序列化已解析的 JSON 会改变空白与键顺序,导致签名不匹配
- 确认密钥复制完整(没有多余的空格或换行)
- 记住签名请求头带有
sha256=前缀
投递因 4xx 响应失败
4xx 错误(例如 401、404、422)是永久性的,不会重试。先修好端点那边的问题(认证、路由、载荷校验),再从投递日志里使用重新投递。
我的 Webhook 被自动暂停了
在连续 5 次投递死亡之后,ColdSend 会自动暂停该 Webhook。查看投递日志找到根本错误,修好端点后再重新启用它。
常见问题
我可以创建多少个 Webhook? 可以创建多个 Webhook,每个都有自己的端点和事件类型选择——比如一个给 CRM,一个给 Slack 通知。
我会收到所有营销活动的事件吗? 会——一个 Webhook 接收整个工作区(所有营销活动)的事件,只按你选择的事件类型过滤。
如果我的端点挂了会怎样? ColdSend 会用指数退避重试(约 1 分钟、约 5 分钟、约 30 分钟)。如果全部重试失败,这次投递会被标记为 dead。连续 5 次投递死亡后,Webhook 会被自动暂停。
我可以为现有的 Webhook 获取新的签名密钥吗? 不行——密钥只在创建时显示一次,无法再次查看或重新生成。要轮换密钥,请删除该 Webhook 并新建一个。
Webhook 投递是否保证恰好一次?
不保证——投递是至少一次。极少数情况下,同一事件可能被投递两次。请在你这边用 event_id 字段去重。
ColdSend 会补发我创建 Webhook 之前发生的事件吗? 不会。你只会收到 Webhook 创建并启用之后发生的事件。