关于 broadcast-campaign
broadcast-campaign 是用于构建 Zavu 多收件人消息活动(包括批量邮件)的技能,面向需要管理群发的开发者。它涵盖活动创建、联系人管理、审核与排期,以及进度监控和拒绝处理。
主要功能
- 01创建跨消息渠道的群发活动
- 02批量添加联系人并设置变量
- 03提交审核、排期、暂停或取消活动
- 04跟踪发送进度和收件人状态
- 05处理内容审核拒绝及重试
适用场景
- 01发送批量邮件简报
- 02安排多收件人 SMS 活动
- 03监控送达情况和失败收件人
- 04修改内容审核未通过的群发
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zavudev/ zavu-skills --skill broadcast-campaign安装后在 Claude Code 中输入/broadcast-campaign确认已加载。
详细介绍
广播活动
适用场景
在构建用于向多个收件人发送消息的活动代码时使用此技能,包括批量邮件。涵盖从创建到监控的完整广播生命周期。
广播生命周期
draft -> pending_review -> pending_admin_review -> approved -> sending -> completed
-> rejected -> (edit) -> pending_review (retry, max 3)
-> rejected -> escalated (manual review by Zavu team)
-> rejected_final
approved -> scheduled -> sending -> completed
sending -> paused (can resume)
draft | pending_review | pending_admin_review | approved
| rejected | escalated | scheduled | sending -> cancelled
(any) -> failed (permanent failure)
分步工作流
1. 创建广播
const result = await zavu.broadcasts.create({
name: "Black Friday Sale",
channel: "sms", // smart | sms | sms_oneway | whatsapp | telegram | email
text: "Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20",
});
const broadcastId = result.broadcast.id; // brd_xxx
Python:
result = zavu.broadcasts.create(
name="Black Friday Sale",
channel="sms",
text="Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20",
)
broadcast_id = result.broadcast.id
Go:
result, err := client.Broadcasts.Create(context.TODO(), zavudev.BroadcastCreateParams{
Name: zavudev.String("Black Friday Sale"),
Channel: zavudev.String("sms"),
Text: zavudev.String("Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20"),
})
broadcastID := result.Broadcast.ID
Ruby:
result = client.broadcasts.create(
name: "Black Friday Sale",
channel: "sms",
text: "Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20",
)
broadcast_id = result.broadcast.id
PHP:
$result = $client->broadcasts->create([
'name' => 'Black Friday Sale',
'channel' => 'sms',
'text' => 'Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20',
]);
$broadcastId = $result->broadcast->id;
渠道选项
| 渠道 | 描述 |
|---|---|
smart | 为每位联系人智能选择路由 |
sms | 向所有联系人发送 SMS |
sms_oneway | 单向 SMS(不接收回复)——无需号码和凭据 |
whatsapp | WhatsApp(向非会话窗口内的联系人发送时需要模板) |
telegram | Telegram。收件人是已向你的机器人发送过消息的用户的数字聊天 ID(838360395 或 telegram:838360395);机器人无法主动发起聊天,且不接受电话号码 |
email | 邮件(需要 emailSubject)——批量邮件的推荐方式 |
消息类型
| 类型 | 描述 |
|---|---|
text | 纯文本(默认) |
image | 带可选说明文字的图片 |
video | 视频消息 |
audio | 音频消息 |
document | 文档文件 |
template | WhatsApp 预先批准的模板 |
邮件广播(带 HTML 正文)
对于批量邮件活动,请使用带 HTML 正文的 channel: "email"。这是通过 Zavu 发送群发邮件的推荐方式。
邮件广播需要付费套餐。在免费套餐中,发送或安排邮件广播会返回 402,并带有 code: "paid_plan_required"(仍可创建草稿)。smart 广播仍会发送,但其中的邮件收件人会失败,并返回 errorCode: "PAID_PLAN_REQUIRED"。通过 POST /v1/messages 发送事务性邮件适用于所有套餐。
const result = await zavu.broadcasts.create({
name: "Newsletter",
channel: "email",
emailSubject: "Special offer for {{name}}",
text: "Hi {{name}}, check out our latest sale!", // plain text fallback
emailHtmlBody: "<h1>Hi {{name}}!</h1><p>Check out our latest sale.</p>",
metadata: { campaign_id: "camp_123", region: "US" },
});
2. 添加联系人(批量,每次请求最多 1000 个)
const result = await zavu.broadcasts.contacts.add({
broadcastId: broadcastId,
contacts: [
{ recipient: "+14155551234", templateVariables: { name: "John" } },
{ recipient: "+14155555678", templateVariables: { name: "Jane" } },
],
});
console.log(result.added, result.duplicates, result.invalid);
3. 发送(触发内容审核)
发送群发内容无需在任何渠道验证账户。身份和业务验证可以提高每日上限,但两者都不等于获得群发权限。群发前必须经过内容审核,且无法绕过。
自动审核开始前,群发文本只会审核一次,而非针对每位收件人审核一次。被拒绝的群发会变为 rejected;被标记的群发则需要等待人工审核,即使是在邮件渠道也是如此——邮件通常会在审核通过后立即发送。
whatsapp 群发会跳过审核。 它只能基于模板创建,Meta 会在批准模板时审核业务和内容。实际执行的检查是确认模板已获批准——未获批准的模板会因 400 template_not_approved 被拒绝。由于 WhatsApp 不会进行其他审核,因此这就是唯一的关卡。
之后,每位收件人都会收到一条普通消息,因此每日上限和 +1 SMS 收件人所需的 10DLC 都按收件人分别适用。
审核结果为已批准(正在发送、已安排发送或已准备发送)或未获批准时,团队所有者会收到电子邮件;邮件中会说明原因和后续操作。若群发创建后其发送方被删除,则会在预留任何余额前因 400 sender_not_found 被拒绝;请使用其他发送方创建新的群发。
// Send immediately
await zavu.broadcasts.send({ broadcastId });
// Or schedule
await zavu.broadcasts.send({
broadcastId,
scheduledAt: "2024-01-15T10:00:00Z",
});
草稿不会直接发出——后续处理取决于渠道:
| 群发渠道 | 此调用的操作 |
|---|---|
| 使用 Meta 已批准模板的 WhatsApp | 跳过审核(Meta 已审核模板),并开始发送 |
| 电子邮件 | 自动审核;通过后立即发送 |
| SMS、Telegram、smart 及其他所有渠道 | 自动审核,然后进入 pending_admin_review——由人工批准后才会发送 |
因此,202 表示已接受,而非正在发送。请轮询状态,不要自行假定;只有基于 WhatsApp 模板的群发会立即进入 sending。
对已处于 approved 或 scheduled 状态的群发调用发送,会直接发送或重新安排发送时间,因为它们已通过审核。
余额无法支付预估费用时,发送操作会返回 402,顶层采用通用错误结构:{ code: "insufficient_balance", message, details: { totalBalance, reservedBalance, availableBalance } }。为兼容较旧的集成,同一对象也会在 error 下重复返回。
4. 监控进度
const progress = await zavu.broadcasts.progress({ broadcastId });
console.log(`${progress.percentComplete}% complete`);
console.log(`Delivered: ${progress.delivered}, Failed: ${progress.failed}, Skipped: ${progress.skipped}`);
console.log(`Estimated completion: ${progress.estimatedCompletionAt}`);
每位联系人的状态:
pending、queued、sending:尚未交由服务提供方处理。sent:服务提供方已接受消息;尚未确认送达。渠道报告送达状态后,收件人会转为delivered或failed。从不报告送达状态的渠道会使收件人保持sent。delivered:渠道已确认消息送达设备(WhatsApp 的已读回执也计入)。failed:未送达。服务提供方延迟报告故障时,收件人可从sent或delivered转为failed。skipped:未发送,因为收件人已选择退出该渠道,或群发在处理到该收件人之前已取消。
进度响应和群发对象会分别以 sent 和 sentCount 表示 sent 计数;在 GET /v1/broadcasts/{broadcastId}/contacts 中,sent 也是有效的 status 筛选条件。SDK 尚未为这些字段提供类型,因此请从 REST 响应中读取:
curl -s https://api.zavu.dev/v1/broadcasts/$BROADCAST_ID/progress \
-H "Authorization: Bearer $ZAVU_API_KEY"
# { "total": 500, "sent": 120, "delivered": 360, "failed": 20, ... }
完成计数会将 sent 视为已完成,因此处于 completed 状态的群发仍可能有收件人正在等待送达回执。
5. 处理拒绝(内容审核失败时)
// Check remaining review attempts
const broadcast = await zavu.broadcasts.get({ broadcastId });
console.log(`Review attempts: ${broadcast.reviewAttempts}/3`);
// Edit content
await zavu.broadcasts.update({
broadcastId,
text: "Updated message content with {{name}}",
});
// Retry review (max 3 attempts)
await zavu.broadcasts.retryReview({ broadcastId });
// Or escalate to manual review
await zavu.broadcasts.escalate({ broadcastId });
其他操作
// Reschedule
await zavu.broadcasts.reschedule({
broadcastId, scheduledAt: "2024-01-16T14:00:00Z",
});
// Cancel (pending contacts skipped, queued may still deliver). Allowed from
// draft, pending_review, pending_admin_review, approved, rejected, escalated,
// scheduled and sending; not from paused or a finished status. Any reserved
// balance is released.
await zavu.broadcasts.cancel({ broadcastId });
// List contacts in broadcast
const contacts = await zavu.broadcasts.contacts.list({
broadcastId, status: "delivered", limit: 100,
});
// Delete (draft only)
await zavu.broadcasts.delete({ broadcastId });
模板变量
在群发文本中使用 {{variable_name}}。通过 templateVariables 为每位联系人单独设置覆盖值:
await zavu.broadcasts.contacts.add({
broadcastId,
contacts: [
{ recipient: "+14155551234", templateVariables: { name: "John", order_id: "ORD-001" } },
],
});
限制
- 每次
add请求最多添加 1000 个联系人(列表较大时请分批处理) - 通过任何渠道发送都无需验证账户。群发是否受限取决于下文的内容审核;起草无需任何条件
- 邮件群发需要付费计划:在 Free 计划下,发送会返回
402 paid_plan_required - 每位收件人都会占用相应渠道的每日限额(参见
send-message技能);达到限额后,其余收件人会被标记为failed,并带有errorCode: "DAILY_LIMIT_EXCEEDED",且不会在次日重试 - 发送前会审核内容,但使用 Meta 已批准模板的 WhatsApp 消息除外
- 自动审核通过后,大多数渠道还需等待人工审核(
pending_admin_review);邮件是例外,会直接发送,除非审核要求人工处理 - 发送时会预留余额(估算费用)
- 最多可重试审核 3 次,之后会升级处理
- 只能更新或删除处于
draft状态的群发 - 取消操作不会停止已排队的消息