API 密钥和 Webhook
Mail Merge 为开发者和无代码构建者提供 REST API 和出站 Webhook。使用 API 密钥,你的脚本可以执行网页应用能做的一切: 读取你的账户、列出模板和联系人、发送活动并跟踪收件人。使用 Webhook,Mail Merge 会在活动完成或收件人打开、点击、回复、退信或取消订阅时立即调用 你的 端点,这样 CRM、电子表格或 Slack 频道可以保持同步,无需轮询。
两者都位于 网页应用 中的 Settings → Developers,是 Professional 计划的一部分(参见 定价)。如果你更希望通过 AI 助手而不是编写代码来与 Mail Merge 通信,可以改用 MCP 服务器: 它在所有计划中都将相同功能作为工具公开。
API 密钥
Section titled “API 密钥”- 打开 Settings → Developers → API keys 并点击 Create key。
- 按照使用位置命名(
Zapier、CRM sync),这样你以后可以撤销正确的密钥。 - 复制密钥。它只显示一次: Mail Merge 只保存它的哈希值。如果丢失,撤销它并创建新的。
每个账户最多可以有 10 个密钥。撤销密钥会立即使用它发出的每个请求都失败;该行从列表中消失。
在每个请求上将密钥作为 Bearer 令牌发送,针对卡片上显示的基础 URL:
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 文档;如果你需要客户端生成器的架构,请 联系我们。
错误和速率限制
Section titled “错误和速率限制”失败是真实的 HTTP 状态,带有一个信封:
{ "error": { "code": "professional_plan_required", "message": "API access is a Professional plan feature" } }| 状态 | code | 含义 |
|---|---|---|
| 401 | 未知或已撤销的密钥,或账户的 Google 访问需要重新连接。 | |
| 403 | professional_plan_required | 密钥的账户不再在 Professional 计划上。密钥在降级时不会被删除;当计划恢复时它们会再次工作。 |
| 429 | rate_limited | 一个密钥上超过 每分钟 600 个请求。等待一分钟后重试。 |
| 400 / 404 / 409 | bad_request、not_found、conflict 等 | 请求本身,带有说明要修复的内容的消息。 |
速率限制按每个 API 服务器实例上的每个密钥计数,所以有效上限是”大约每分钟 600 个”: 不要围绕击中它进行设计。
Webhook
Section titled “Webhook”- 打开 Settings → Developers → Webhooks 并点击 Add webhook。
- 输入一个 HTTPS URL(纯
http://被拒绝)并勾选它应该接收的事件。 - 在新行上点击 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-Signature | sha256= 后跟原始正文的十六进制 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()})# Pythonimport 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 "")Zapier、Make 和 n8n
Section titled “Zapier、Make 和 n8n”无需代码: 创建一个 Catch Hook(Zapier Webhooks by Zapier)、一个 Custom webhook(Make)或一个 Webhook 触发节点(n8n),将它给你的 URL 粘贴为端点,勾选事件,并点击 Send test 以便工具可以采样有效负载。data 字段成为你映射到下一步的变量(向工作表添加行、更新 CRM 联系人、发送到 Slack)。这些工具默认不验证签名;它们给你的 URL 是不可猜测的,这是它们依赖的保护。
下一步去哪里
Section titled “下一步去哪里”- AI 代理(MCP),如果助手应该为你驱动 Mail Merge 而不是脚本。
- 活动,了解收件人端点中的状态含义。
- 定价,了解 Professional 计划包含的内容。