跳转到内容

API 密钥和 Webhook

Mail Merge 为开发者和无代码构建者提供 REST API 和出站 Webhook。使用 API 密钥,你的脚本可以执行网页应用能做的一切: 读取你的账户、列出模板和联系人、发送活动并跟踪收件人。使用 Webhook,Mail Merge 会在活动完成或收件人打开、点击、回复、退信或取消订阅时立即调用 你的 端点,这样 CRM、电子表格或 Slack 频道可以保持同步,无需轮询。

两者都位于 网页应用 中的 Settings → Developers,是 Professional 计划的一部分(参见 定价)。如果你更希望通过 AI 助手而不是编写代码来与 Mail Merge 通信,可以改用 MCP 服务器: 它在所有计划中都将相同功能作为工具公开。

  1. 打开 Settings → Developers → API keys 并点击 Create key。
  2. 按照使用位置命名(Zapier、CRM sync),这样你以后可以撤销正确的密钥。
  3. 复制密钥。它只显示一次: Mail Merge 只保存它的哈希值。如果丢失,撤销它并创建新的。

每个账户最多可以有 10 个密钥。撤销密钥会立即使用它发出的每个请求都失败;该行从列表中消失。

在每个请求上将密钥作为 Bearer 令牌发送,针对卡片上显示的基础 URL:

Terminal window
curl https://merge.email/api/v1/me \
-H "Authorization: Bearer mm_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

密钥作为创建它的账户行动,完全像已登录的会话: 相同的 Google 授权、相同的每日配额、相同的计划限制。没有单独的”API 用户”。

API 是网页应用使用的相同 /v1 表面,所以你在屏幕上能做的任何事都有一个端点支持它。集成最常使用的:

调用功能
GET /v1/me账户: 计划、每日配额(最大值、已用、剩余)、时区、模板元数据。
GET /v1/templates · GET /v1/templates/{templateId}你保存的模板;正文按模板加载。
GET /v1/contacts · POST /v1/contacts联系人簿(使用 limit / cursor → nextCursor 分页)。
POST /v1/campaigns从 Google Sheet 发送、安排或自动化活动。正文与活动构建器发送的相同: 工作表、收件人列列、主题和正文带有 {{merge tags}},以及发送选项。
GET /v1/campaigns · GET /v1/campaigns/{campaignId}/recipients你的活动和每个收件人的状态(已发送、已读、已点击、已回复、已退信、已取消订阅)。
POST /v1/campaigns/{campaignId}/status暂停、恢复或停止正在运行的活动。
POST /v1/recipients/verify电子邮件验证器。

请求和响应正文是 JSON。完整的类型化表面从服务器生成为 OpenAPI 文档;如果你需要客户端生成器的架构,请 联系我们。

失败是真实的 HTTP 状态,带有一个信封:

{ "error": { "code": "professional_plan_required", "message": "API access is a Professional plan feature" } }
状态code含义
401未知或已撤销的密钥,或账户的 Google 访问需要重新连接。
403professional_plan_required密钥的账户不再在 Professional 计划上。密钥在降级时不会被删除;当计划恢复时它们会再次工作。
429rate_limited一个密钥上超过 每分钟 600 个请求。等待一分钟后重试。
400 / 404 / 409bad_request、not_found、conflict 等请求本身,带有说明要修复的内容的消息。

速率限制按每个 API 服务器实例上的每个密钥计数,所以有效上限是”大约每分钟 600 个”: 不要围绕击中它进行设计。

  1. 打开 Settings → Developers → Webhooks 并点击 Add webhook。
  2. 输入一个 HTTPS URL(纯 http:// 被拒绝)并勾选它应该接收的事件。
  3. 在新行上点击 Send test: Mail Merge 发送一个 ping,提示会告诉你你的端点如何应答。

每个端点都有自己的 签名密钥(whsec_…),显示在行上并带有复制按钮。每个账户最多可以有 5 个端点。

事件何时data
campaign.completed活动的最后一封电子邮件已处理。campaignId、name、status: "completed"、sentCount、campaignSize
campaign.paused · campaign.resumed · campaign.stopped你暂停、恢复或停止了活动。campaignId、name、status(paused / active / stopped)、sentCount
email.opened收件人打开了电子邮件,每个活动仅第一次。campaignId、recipient、at
email.clicked收件人点击了跟踪链接,每次点击。campaignId、recipient、at、url
email.replied在已发送的线程上检测到回复。campaignId、recipient、at
email.bounced检测到退信。campaignId、recipient、at
recipient.unsubscribed收件人使用了取消订阅链接,每个活动仅第一次。campaignId、recipient、at、method

打开和点击需要为活动 启用跟踪;回复和退信来自每个已发送活动后的回复扫描。

Mail Merge 为每个订阅端点的每个事件发送一个 POST,带有 JSON 正文:

{
"id": "6f1c2d3e-…",
"event": "email.opened",
"createdAt": "2026-10-15T14:03:21.512Z",
"data": { "campaignId": "…", "recipient": "ada@example.com", "at": "2026-10-15T14:03:21.498Z" }
}

和三个标头:

标头值
X-MailMerge-Event事件名称,与正文中的 event 相同。
X-MailMerge-Delivery投递 id,与 id 相同。用它来忽略重复。
X-MailMerge-Signaturesha256= 后跟原始正文的十六进制 HMAC-SHA256,用端点的密钥作为密钥。

在 5 秒内 用任何 2xx 应答。在网络错误或 5xx 上,Mail Merge 重试一次,在 2 秒后;4xx 被视为你的判决并不重试。重试时发送相同的投递 id。在 连续 20 次失败投递后,端点被 禁用,行会显示这一点: 修复端点,然后删除并重新添加它。任何成功的投递都会重置计数器。

事件至少投递一次,顺序不保证。打开特别是成批到达(每个呈现跟踪像素的邮件客户端),所以在 X-MailMerge-Delivery 或 (event、campaignId、recipient) 上使你的处理程序幂等。

始终在信任有效负载之前验证。计算 原始请求正文(确切的字节,在任何 JSON 解析之前)上的 HMAC 并以恒定时间比较:

// Node.js (Express with `express.raw({ type: "application/json" })`)
import { createHmac, timingSafeEqual } from "node:crypto"
export function verifyMailMergeSignature(rawBody, signatureHeader, secret) {
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex")
const a = Buffer.from(expected)
const b = Buffer.from(signatureHeader ?? "")
return a.length === b.length && timingSafeEqual(a, b)
}
app.post("/mailmerge", (req, res) => {
if (!verifyMailMergeSignature(req.body, req.get("X-MailMerge-Signature"), process.env.MAILMERGE_WEBHOOK_SECRET)) {
return res.status(401).end()
}
const payload = JSON.parse(req.body)
// … handle payload.event / payload.data
res.status(204).end()
})
# Python
import hashlib, hmac
def verify_mailmerge_signature(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header or "")

无需代码: 创建一个 Catch Hook(Zapier Webhooks by Zapier)、一个 Custom webhook(Make)或一个 Webhook 触发节点(n8n),将它给你的 URL 粘贴为端点,勾选事件,并点击 Send test 以便工具可以采样有效负载。data 字段成为你映射到下一步的变量(向工作表添加行、更新 CRM 联系人、发送到 Slack)。这些工具默认不验证签名;它们给你的 URL 是不可猜测的,这是它们依赖的保护。

  • AI 代理(MCP),如果助手应该为你驱动 Mail Merge 而不是脚本。
  • 活动,了解收件人端点中的状态含义。
  • 定价,了解 Professional 计划包含的内容。