WhatsApp 模板
由企业发起的 WhatsApp 消息必须使用预先审核通过的模板。模板包含固定文本和变量,因此发送时只需提供 OTP 码或订单号等值。
Bird 提供一套托管模板目录,将其内容注册到 WhatsApp,并通过 Bird 自有号码发送;这些模板的 slug 以 bird_ 开头。已接入自有号码的工作区还可以在自己的 WhatsApp Business Account 上创建模板。Approved templates 页面列出工作区可以发送的所有模板及其呈现效果。

在控制台中浏览模板
在 WhatsApp > Approved templates 中打开 Approved templates。Your templates 包含本工作区创建的模板;All templates 还会加入 Bird 托管目录。可以按名称搜索,或按状态和类别筛选,并通过筛选器旁的切换按钮在卡片网格和列表视图之间切换。
在列表视图中,每一行显示选择和发送模板所需的字段:
- Status:模板整体是否可以发送。托管目录模板显示
active;自有模板显示其审核所处的状态。请查看语言列表,确认所需语言可用。 - Name:显示名称,下方是模板的
slug。发送时请使用slug。 - Languages:模板已注册的语言,例如英语和荷兰语。
- Category:
authentication、utility或marketing。类别决定 WhatsApp 如何处理该消息、托管模板从哪个 Bird 号码发送,并与目标国家共同决定价格。 - WABA:目录模板显示 Bird-managed。你自己的模板显示持有它的 WhatsApp Business Account,且只能从该账户下的号码发送。
- Updated:模板最后一次更改的时间。
点击某一行即可打开该模板的详情。
模板包含哪些内容
详情视图以 WhatsApp 风格的预览呈现消息正文、变量和按钮。
详情中还提供一个调用 POST /v1/whatsapp/messages 的 cURL 示例,其中使用区域主机和模板的示例值。发送前请替换 API 密钥、收件人和变量值。
通过该示例可以最快了解发送请求必须符合的结构。通过 API 时,相同内容来自模板的版本(读取模板内容)。
通过 API 列出模板
GET /v1/whatsapp/templates 返回基于游标分页的目录。该请求需要 whatsapp_management 读取权限。请使用 HTTP 或 SDK 的原始请求方法。
type Templates = { data: Array<{ slug: string; status: string }> };
const templates = await bird.request<Templates>({
method: "GET",
path: "/v1/whatsapp/templates",
});templates = client.get("/v1/whatsapp/templates")var out struct {
Data []struct {
Slug string `json:"slug"`
Status string `json:"status"`
} `json:"data"`
}
if err := client.Get(context.Background(), "/v1/whatsapp/templates", &out); err != nil {
log.Fatal(err)
}$templates = $bird->get('/v1/whatsapp/templates');curl https://us1.platform.bird.com/v1/whatsapp/templates \
-H "Authorization: Bearer $BIRD_API_KEY"每个条目标明模板、其类别及可用语言。如需消息内容,请另行读取当前生效的版本。
{
"available_languages": ["en", "es", "pt-BR", "..."],
"category": "authentication",
"default_language": "en",
"description": "One-time passcode",
"id": "wat_01ky4x8e4genzb7way45txfkm1",
"languages": {
"en": { "status": "approved" },
"es": { "status": "approved" },
"pt-BR": { "status": "approved" },
"...": "..."
},
"name": "bird_otp",
"on_missing_language": "fail",
"scope": "system",
"slug": "bird_otp",
"status": "active"
}示例响应省略了部分 bird_otp 语言列表。
发送所依赖的字段:
slug:发送时使用的标识。托管模板的 slug 以bird_开头,该前缀专为托管模板保留。waba:在 Meta 持有该模板各语言版本的 WhatsApp Business Account,发送号码也必须属于该账户。托管模板没有此字段,因为其账户由 Bird 管理。available_languages:可以发送的语言。某个语言被暂停、停用、归档或受限后,会从此列表中移除。on_missing_language:请求的语言不可用时的处理方式。Bird 托管的 WhatsApp 模板使用fail,此时会拒绝发送,而不是改用其他语言。
状态与语言状态
Bird 托管模板报告 status: active。languages.<tag>.status 报告 WhatsApp 对单个语言的状态,例如 approved、paused 或 disabled。
处于活跃状态的模板仍可能包含不可用的语言。请根据 available_languages 判断某个语言是否可以发送。
读取模板内容
消息内容属于当前生效版本中的某个语言。先从模板读取 live_version_id,再请求所需的语言:
const language = await bird.request({
method: "GET",
path: "/v1/whatsapp/templates/bird_order_confirmation/versions/{version_id}/languages/en",
});language = client.get(
"/v1/whatsapp/templates/bird_order_confirmation/versions/{version_id}/languages/en"
)var language map[string]any
if err := client.Get(context.Background(),
"/v1/whatsapp/templates/bird_order_confirmation/versions/{version_id}/languages/en",
&language); err != nil {
log.Fatal(err)
}$language = $bird->get('/v1/whatsapp/templates/bird_order_confirmation/versions/{version_id}/languages/en');curl https://us1.platform.bird.com/v1/whatsapp/templates/bird_order_confirmation/versions/{version_id}/languages/en \
-H "Authorization: Bearer $BIRD_API_KEY"模板引用接受 slug 或 wat_ ID。GET …/versions/{version_id}/languages 列出该版本的语言,但不包含其内容。
{
"category": "utility",
"components": [
{
"example_parameters": [
{ "name": "ref", "text": "A1B2C3D4", "type": "text" },
{ "name": "amount", "text": "USD 49.99", "type": "text" }
],
"text": "Your order {{ref}} has been confirmed for a total of {{amount}}. Thanks for shopping with us.",
"type": "body"
}
],
"language": "en",
"status": "approved"
}发送时按名称填充这些占位符,example_parameters 用于标识每个占位符。在此示例中,发送请求的 parameters 接受键 ref 和 amount。位置参数模板的键是其编号,例如 1,但有两个例外:身份验证模板的验证码使用 code,url 按钮的编号后缀使用 button_url。带参数的按钮有各自的 example_parameters。
语言的 category 是 Meta 用于计费的类别。如果 Meta 对该语言重新分类,它可能与模板注册时的类别不同。
版本的 variables 列表汇总了每个占位符的键、类型、是否必填及约束条件。命名占位符以其名称作为键。位置占位符以其编号作为键,但身份验证码(code)和 url 按钮的后缀(button_url)除外。发送请求的 parameters 使用这些键。
使用模板发送
在发送请求的 template 对象中指定模板,并通过 parameters 填入变量;完整载荷请参阅发送 WhatsApp 消息:
const msg = await bird.whatsapp.send({
to: "+15551234567",
template: {
slug: "bird_otp",
parameters: { code: "123456" },
},
});
console.log(msg.id, msg.status);msg = client.whatsapp.send(
to="+15551234567",
template="bird_otp",
language="en",
parameters={"code": "123456"},
)
print(msg.id, msg.status)msg, err := client.Whatsapp.Send(context.Background(), bird.WhatsappSendParams{
To: "+15551234567",
Template: "bird_otp",
Language: "en",
Parameters: map[string]any{"code": "123456"},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)$message = $bird->whatsapp->send(
to: '+15551234567',
template: 'bird_otp',
language: 'en',
parameters: ['code' => '123456'],
);
echo $message->getId(), ' ', $message->getStatus();bird whatsapp send \
--language en \
--parameters '{"code":"123456"}' \
--template bird_otp \
--to +15551234567curl -X POST https://us1.platform.bird.com/v1/whatsapp/messages \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155550100",
"template": {
"slug": "bird_otp",
"language": "en",
"parameters": { "code": "481920" }
}
}'按类别发送
每个模板都属于 Meta 三个类别之一。类别决定了发送成功前需要完成哪些准备,也决定了费用。自行创建或复制身份验证模板需要经过验证的企业,但发送这类模板不需要:Bird 托管的 bird_otp 位于 Bird 自己的 WhatsApp Business Account 上,无需您完成任何验证即可发送。营销模板始终从您自己的 WhatsApp Business Account 发送,经由 Meta 的另一个 API,Bird 会自动路由到该处。三类模板中,实用模板的前提条件最少。
后续步骤
- 发送 WhatsApp 消息:
template对象所在的完整发送载荷 - WhatsApp 模板准则:Meta 审核模板所依据的规则
- 身份验证模板:一次性验证码,以及创建此类模板前需要通过的企业验证
- WhatsApp 定价:类别和目的地如何决定价格