编写 WhatsApp 模板
Bird 的托管目录涵盖了常见场景,但要使用你自己措辞的模板,则需要在你已连接的 WhatsApp Business Account 上编写。本页介绍如何创建模板;WhatsApp 模板介绍如何浏览和发送现有模板。
整个流程由三件事决定:
- 模板包含版本,版本包含每种语言的一个条目。 实际发送的是某个版本中的某种语言,而不是模板本身。
- 内容写入草稿。 一个模板最多有一个打开的草稿,在你提交之前,草稿中的任何内容都不会到达 WhatsApp。
- 审批按语言返回。 同一版本中,一种语言可能获批,而另一种被拒绝。
开始之前
你需要连接一个属于你自己的号码,这样你的工作区才能获得一个可用于编写模板的 WhatsApp Business Account。未连接的账号会被拒绝,编辑 Bird 内置的 bird_ 模板也会被拒绝:这些模板在 Bird 自己的账号上,请改为将其复制到你的账号上。
编写 authentication 模板还需要经过验证的企业;utility 和 marketing 类别则不需要。相关门槛请参阅身份验证模板。
在仪表板中
New template 提供两种方式。Start with a template 会打开模板库,这是最快的方式:选择一个内容已接近你需求的模板(包括 Bird 的模板),副本会作为打开的草稿出现在你的账号上。

Start from scratch 要求你选择类别、输入名称并设置默认语言,然后打开编辑器。marketing 模板还需要选择消息类型。名称会成为 slug,而 slug 和类别是之后无法更改的两项选择。

编辑器一次编写一种语言:侧边栏列出模板的各种语言及其审核状态,中间栏放置内容,手机预览以替换后的示例值渲染消息。

编辑器会随模板类型改变布局。carousel 模板在消息旁为每张卡片添加一个标签页,每张卡片都必须重复卡片 1 的结构:相同的头部格式和相同顺序的按钮。

authentication 模板没有消息编辑器。WhatsApp 会编写文案,因此编辑器只提供生成文案所需的两个设置:Add security recommendation 和 Code expiration (minutes)。

Save as draft 保存你的工作,不会联系 WhatsApp。Submit for review 冻结版本并将其发送到 WhatsApp。下文介绍的 CLI 提交执行相同的冻结操作。
两种起步方式
复制现有模板
复制操作将源模板的内容作为打开的草稿,且不会调用 WhatsApp,因此在你主动选择之前不会提交任何内容。在复制之前,有两点值得了解:
- 类别继承自源模板,且无法更改。 如果你需要不同的类别,请改为从头创建。
- 你只能缩减语言范围,不能增加。 一个包含 70 种语言的目录模板不必变成你的 70 种语言:只选择你实际会维护的子集。请求源模板不包含的语言会被拒绝并返回 E15060,响应中会指明哪些语言不匹配。之后可以向副本添加更多语言。
语言子集是一个数组,因此需要放在请求体中而不是作为标志传递:
代码示例
bird whatsapp templates duplicate bird_order_confirmation --body-file copy.json代码示例
{
"waba": "102290129340398",
"slug": "acme_order_update",
"include_languages": ["en", "es-ES"],
"default_language": "en"
}省略 include_languages,副本会继承源模板的所有语言。省略 default_language,当你的子集仍包含源模板的默认语言时,副本会保留该默认语言;否则会取副本语言中按规范标签排序的第一个,这不一定是你列出的第一个,因此如有需要请显式设置。
从头创建
创建模板需要 slug、账号、类别和默认语言:
代码示例
bird whatsapp templates create order_update \
--waba 102290129340398 \
--category utility \
--default-language enslug 和类别都是永久性的。 WhatsApp 根据 slug 派生自己的模板名称,两者之后都无法更改;需要不同的就意味着创建新模板。bird_ 前缀为 Bird 的目录所保留。你选择的类别不一定是发送时的计费类别:Meta 会按语言应用自己的类别并可能调整,价格以 Meta 的为准。
编写各语言内容
打开草稿,然后一次编写一种语言:
代码示例
bird whatsapp templates versions create order_update
bird whatsapp templates versions languages set order_update <version-id> en --body-file en.json打开草稿可以安全地重复调用:模板只有一个草稿,因此会返回已打开的那个,而不会创建第二个。模板也会将其报告为 draft_version_id。
写入语言会替换整个语言内容,而不是合并。 文件每次都携带该语言的完整 components,因此请先读取语言内容再整体写回;只发送你修改的部分会删除其余内容。
每个变量都需要一个示例值。 WhatsApp 审核的是填充后的消息而非模板本身,因此包含占位符但没有示例参数的块会在提交时而非写入时被拒绝。
检查后提交
在冻结任何内容之前先进行验证。仅验证的提交会对每种语言运行所有检查,并在一次调用中报告每个问题,不会向 WhatsApp 发送任何内容:
代码示例
bird whatsapp templates versions submit order_update <version-id> --validate-only阅读 valid 和 errors;每个错误会指明语言、字段以及实际提交时会失败的错误码。然后去掉该标志进行正式提交。正式提交会将草稿冻结为不可变版本并返回 202。检查和提交请使用不同的幂等键,因为对已更改的请求体重用同一个键会被拒绝。
只有内容与已批准副本不同的语言才会发送到 WhatsApp。已匹配的语言会继承其批准状态,因此如果没有任何更改,提交会立即完成,无需轮询。之后不会自动打开替换草稿:下一轮编辑从重新创建草稿开始。
仅验证的通过并不能预测 WhatsApp 的决定。WhatsApp 没有提前查询的途径,因此它仍然可能拒绝通过了所有本地检查的内容。
关注审核进度
审批稍后到达,且按语言返回。当任何语言尚未决定时,模板的 pending_version_id 保持已设置状态,每种语言的列表携带各自的结果:
- approved 可发送。模板上的 available_languages 正是当前发送可以解析使用的语言列表。
- rejected、submit_failed、paused 需要在新草稿中进行编辑。WhatsApp 接受对已暂停语言的编辑,重新提交即可清除该状态。
- disabled、limit_exceeded、in_appeal 完全拒绝编辑;需要重新读取其状态,直到 WhatsApp 更新这些状态。
模板自身的 status 是一个聚合值:active 表示至少有一种语言可发送,而非全部。
发送你编写的模板
你编写的模板通过与其他模板相同的端点发送,与 Bird 目录的一个区别是:你必须指定 from,且该号码必须属于与模板相同的 WhatsApp Business Account。使用不同账号的发送者会在计费之前被拒绝,返回 422 E15023。
模板可以通过 language_source_required 要求指定接收者语言。否则,on_missing_language 控制解析是直接失败,还是可以使用已批准的基础语言或 default_language。请针对模板已批准的 available_languages 测试配置的策略;未批准的默认语言不可发送。你提供的值必须填充实际解析到的语言的占位符,因此发送前请先读取该语言的内容。完整载荷请参阅发送 WhatsApp 消息。
注意事项
- 最新版本不一定是发送中的版本。 版本列表按最新排序,且包含任何打开的草稿,因此最上面一行通常是草稿或仍在审核中的版本。模板将正在使用的版本标记为 live_version_id;没有活跃版本的模板完全无法发送。
- 审核中的语言拒绝写入。 WhatsApp 会锁定该语言直到审核完成,因此在 pending 期间的编辑会失败而不是排队等待。
- 列表行不包含内容。 列出模板只能找到模板并显示生命周期状态;读取模板的实际内容需要进行版本读取。
- 删除不可恢复。 丢弃一种语言、删除草稿和删除模板都需要显式确认,删除模板会停止该 slug 下的所有发送。
后续步骤
- WhatsApp 模板:目录、类别以及共享的按模板发送契约
- 模板指南:Meta 审核关注的内容
- 电话号码设置:连接你用于编写模板的账号
- 发送 WhatsApp 消息:完整的发送载荷
- 创建和提交 WhatsApp 模板:一段编写 utility 模板和 marketing carousel 的视频
相关资源
继续查阅此主题的文档、指南和示例。资源为英文。