Sign inGet started

编写 WhatsApp 模板

Bird 的托管目录涵盖了常见场景,但要使用你自己措辞的模板,则需要在你已连接的 WhatsApp Business Account 上编写。本页介绍如何创建模板;WhatsApp 模板介绍如何浏览和发送现有模板。
整个流程由三件事决定:
  • 模板包含版本,版本包含每种语言的一个条目。 实际发送的是某个版本中的某种语言,而不是模板本身。
  • 内容写入草稿。 一个模板最多有一个打开的草稿,在你提交之前,草稿中的任何内容都不会到达 WhatsApp。
  • 审批按语言返回。 同一版本中,一种语言可能获批,而另一种被拒绝。

开始之前

你需要连接一个属于你自己的号码,这样你的工作区才能获得一个可用于编写模板的 WhatsApp Business Account。未连接的账号会被拒绝,编辑 Bird 内置的 bird_ 模板也会被拒绝:这些模板在 Bird 自己的账号上,请改为将其复制到你的账号上。
编写 authentication 模板还需要经过验证的企业;utility 和 marketing 类别则不需要。相关门槛请参阅身份验证模板
你可以在仪表板的 WhatsApp > Templates 下编写模板,也可以使用 bird CLI,或通过 MCP 服务端。仪表板遵循本页描述的相同步骤;后续示例使用 CLI。

在仪表板中

New template 提供两种方式。Start with a template 会打开模板库,这是最快的方式:选择一个内容已接近你需求的模板(包括 Bird 的模板),副本会作为打开的草稿出现在你的账号上。
Bird 仪表板中的模板库:模板卡片网格,每张卡片预览其消息内容,并标注名称、slug、状态、类别和语言,旁边有模板来源、类别和语言的筛选器
Start from scratch 要求你选择类别、输入名称并设置默认语言,然后打开编辑器。marketing 模板还需要选择消息类型。名称会成为 slug,而 slug 和类别是之后无法更改的两项选择。
Bird 仪表板中的创建新模板步骤:Marketing、Utility 和 Authentication 类别磁贴下方有 Name 字段和 Default language 选择器,以及 Create template 按钮
编辑器一次编写一种语言:侧边栏列出模板的各种语言及其审核状态,中间栏放置内容,手机预览以替换后的示例值渲染消息。
Bird 仪表板中 Order update utility 模板的模板编辑器:语言侧边栏中 English 标记为 Approved,旁边是 Dutch,手机预览显示渲染后的消息及其 Track order 和 Contact support 按钮
编辑器会随模板类型改变布局。carousel 模板在消息旁为每张卡片添加一个标签页,每张卡片都必须重复卡片 1 的结构:相同的头部格式和相同顺序的按钮。
Bird 仪表板中 carousel marketing 模板的模板编辑器:消息正文上方有 Message、Card 1、Card 2 和 Card 3 标签页,下方有变量示例区域,旁边手机预览显示消息后跟可滑动的图片卡片,每张卡片带有 Show me 按钮
authentication 模板没有消息编辑器。WhatsApp 会编写文案,因此编辑器只提供生成文案所需的两个设置:Add security recommendationCode expiration (minutes)
Bird 仪表板中 authentication 模板的模板编辑器:Authentication settings 面板包含 Add security recommendation 开关和 Code expiration (minutes) 字段,旁边手机预览显示 WhatsApp 编写的验证码消息及其 Copy code 按钮
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 en
slug 和类别都是永久性的。 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
阅读 validerrors;每个错误会指明语言、字段以及实际提交时会失败的错误码。然后去掉该标志进行正式提交。正式提交会将草稿冻结为不可变版本并返回 202。检查和提交请使用不同的幂等键,因为对已更改的请求体重用同一个键会被拒绝。
只有内容与已批准副本不同的语言才会发送到 WhatsApp。已匹配的语言会继承其批准状态,因此如果没有任何更改,提交会立即完成,无需轮询。之后不会自动打开替换草稿:下一轮编辑从重新创建草稿开始。
仅验证的通过并不能预测 WhatsApp 的决定。WhatsApp 没有提前查询的途径,因此它仍然可能拒绝通过了所有本地检查的内容。

关注审核进度

审批稍后到达,且按语言返回。当任何语言尚未决定时,模板的 pending_version_id 保持已设置状态,每种语言的列表携带各自的结果:
  • approved 可发送。模板上的 available_languages 正是当前发送可以解析使用的语言列表。
  • rejectedsubmit_failedpaused 需要在新草稿中进行编辑。WhatsApp 接受对已暂停语言的编辑,重新提交即可清除该状态。
  • disabledlimit_exceededin_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 下的所有发送。

后续步骤