# WhatsApp 联系人卡片

联系人卡片消息可分享一个或多个联系人：收件人在卡片上看到的姓名，以及从卡片打开的个人资料视图，其中包含电话号码、电子邮件、网站、地址、雇主和生日。用它把同事的号码、快递员的号码或您自己的号码递给客户，无需将数字粘贴到文本中让对方重新手动输入。

## 发送联系人卡片

`contact_cards` 是一个数组。每张卡片需要一个 `name`，且该名称需要 `formatted_name` 加上至少一个其他部分：

**TypeScript**

```typescript
const msg = await bird.whatsapp.send({
  to: "+16505551234",
  from: "+13124495648",
  contact_cards: [
    {
      name: {
        formatted_name: "Barbara J. Johnson",
        first_name: "Barbara",
        last_name: "Johnson",
      },
      phone_numbers: [{ phone_number: "+16505559999", type: "Mobile" }],
    },
  ],
});
console.log(msg.id, msg.status);
```

Examples: [TypeScript](/zh-sg/wendang/guides/whatsapp/message-types/contact-cards.ts.md) · [Python](/zh-sg/wendang/guides/whatsapp/message-types/contact-cards.py.md) · [Go](/zh-sg/wendang/guides/whatsapp/message-types/contact-cards.go.md) · [PHP](/zh-sg/wendang/guides/whatsapp/message-types/contact-cards.php.md) · [CLI](/zh-sg/wendang/guides/whatsapp/message-types/contact-cards.cli.md) · [cURL](/zh-sg/wendang/guides/whatsapp/message-types/contact-cards.curl.md)

`from` 在每条服务消息中都是必填项：一个您的工作区拥有的号码，而非 Bird 托管的号码。

完整结构还包含雇主、生日以及其他联系方式详情数组：

```json
{
  "to": "+16505551234",
  "from": "+13124495648",
  "contact_cards": [
    {
      "name": {
        "formatted_name": "Dr. Barbara J. Johnson Esq.",
        "prefix": "Dr.",
        "first_name": "Barbara",
        "middle_name": "Joana",
        "last_name": "Johnson",
        "suffix": "Esq."
      },
      "org": { "company": "Lucky Shrub", "department": "Legal", "title": "Lead Counsel" },
      "birthday": "1999-01-23",
      "phone_numbers": [
        { "phone_number": "+16505559999", "type": "Landline" },
        { "phone_number": "+19175559999", "type": "Mobile" }
      ],
      "emails": [{ "email": "bjohnson@example.com", "type": "Work" }],
      "urls": [{ "url": "https://example.com", "type": "Company" }],
      "addresses": [
        {
          "street": "1 Lucky Shrub Way",
          "city": "Menlo Park",
          "state": "CA",
          "zip": "94025",
          "country": "United States",
          "country_code": "US",
          "type": "Office"
        }
      ]
    }
  ]
}
```

每个 `type` 标签，无论用在电话、电子邮件、网站还是地址上，都是您自行填写的自由文本，按原样发送，并在收件人的个人资料视图中显示在值的旁边。WhatsApp 未定义这些标签的词汇表，因此 `Mobile`、`Landline`、`Pop-Up` 和 `Work (old)` 都同样有效。

## 卡片获得按钮的条件

以 E.164 格式书写的电话号码（包含国家代码和前导 `+`）会为该卡片赢得一个按钮，点击即可与该号码打开 WhatsApp 聊天。Bird 无法识别为 E.164 的号码仍会按原样显示在卡片上，只是不会获得按钮。

这包括没有前导 `+` 的号码。Bird 不会为您补上：一个国内格式的号码在加上 `+` 后，可能被解析为另一个国家的有效号码，从而将按钮指向一个陌生人。放弃猜测只是少一个按钮；猜错则让收件人与错误的人聊天。

完全不包含电话号码的卡片不会显示聊天按钮，只能被保存到通讯录。

## 限制

| 字段                                                        | 约束                                            | 执行方                  |
| ----------------------------------------------------------- | ----------------------------------------------- | ----------------------- |
| `contact_cards`                                             | 每条消息 1 到 5 张卡片                          | Bird，在接受时（`422`） |
| `name`                                                      | 必填；`formatted_name` 加上至少一个其他名称部分 | Bird，在接受时（`422`） |
| `formatted_name`、`first_name`、`middle_name`、`last_name`  | 最多 256 个字符                                 | Bird，在接受时（`422`） |
| `prefix`、`suffix`                                          | 最多 64 个字符                                  | Bird，在接受时（`422`） |
| `birthday`                                                  | 可选，`YYYY-MM-DD`，且为日历中存在的日期        | Bird，在接受时（`422`） |
| `phone_numbers`、`emails`、`urls`、`addresses`              | 各最多 10 个条目                                | Bird，在接受时（`422`） |
| `phone_number`                                              | 最多 32 个字符                                  | Bird，在接受时（`422`） |
| `email`                                                     | 最多 254 个字符                                 | Bird，在接受时（`422`） |
| `url`                                                       | 最多 2048 个字符，不校验是否为 URL              | Bird，在接受时（`422`） |
| 任意电话、电子邮件、网站或地址上的 `type`                   | 最多 64 个字符的自由文本                        | Bird，在接受时（`422`） |
| `company`、`department`、`title`                            | 最多 128 个字符                                 | Bird，在接受时（`422`） |
| `street`、`city`、`state`、`zip`、`country`、`country_code` | 最多 128 个字符                                 | Bird，在接受时（`422`） |

**五张卡片的上限是 Bird 设定的，且远低于 WhatsApp 所接受的数量。** WhatsApp 自己发布的 API 描述声明上限为五，其文档建议出于可用性和负面反馈原因发送更少，而一打开就是 "Contact 1 and 256 other contacts" 的消息在成为功能之前先是垃圾信息载体。日后提高上限属于增量变更，因此如果五张不够用，请提出需求。

上面的所有长度限制也是 Bird 设定的。WhatsApp 没有施加任何有意义的限制，其客户端也不会补偿：500 个字符的 `type` 会渲染成十行重复字母，4000 个字符的 `url` 会被静默丢弃，使个人资料视图留白。一个指出问题字段的 `422` 胜过一张收件人无法阅读的卡片。

## Schema 无法表达的两条规则

**姓名需要第二个部分。** 仅有 `formatted_name` 会被拒绝，返回 `422` [`E15061`](/docs/api/errors/E15061) `WhatsAppContactNameIncomplete`，指明 `contact_cards.<n>.name`。`prefix`、`first_name`、`middle_name`、`last_name` 或 `suffix` 中的任意一个即可满足要求，但空白或仅含空格的值不算，`org` 也无法弥补。这是 WhatsApp 自身的要求，其参考文档中未有记载；Bird 会在接受时捕获此错误，让您获得可操作的错误而非异步失败。

**生日必须是真实日期。** `birthday` 的格式为 `YYYY-MM-DD`；任何其他格式以及日历中不存在的日期（例如 `2026-02-30`）都会被拒绝，返回 `422` [`E15062`](/docs/api/errors/E15062) `WhatsAppContactBirthdayInvalid`。WhatsApp 本身接受 `2026-02-30` 并将其展示给收件人，看起来像是您数据中的 bug。

## 回读卡片

您发送的卡片通过消息列表或 `GET /v1/whatsapp/messages/{id}` 在入站卡片使用的同一个 `contact_cards` 字段上回读：

```json
{
  "id": "wam_01kyb2m4xq7whs0d8n3prv6tez",
  "direction": "outbound",
  "status": "delivered",
  "contact_cards": [
    {
      "name": { "formatted_name": "Barbara J. Johnson", "first_name": "Barbara" },
      "phone_numbers": [{ "phone_number": "+16505559999", "type": "Mobile" }]
    }
  ]
}
```

您发送的卡片上不存在 `origin` 和 `vcard`：WhatsApp 在联系人分享的卡片上设置这两个字段。您发送的 `type` 标签回读时与原文完全一致，而收到的卡片上的标签会被转为小写。入站侧详见[接收 WhatsApp 联系人卡片](/docs/guides/whatsapp/receiving-whatsapp/contact-cards)。

## 边界情况

- **客服窗口必须处于打开状态。** 联系人卡片发送属于服务消息，仅在打开的窗口内可投递；请参阅 Hub 的[客服窗口](/docs/guides/whatsapp/message-types#the-customer-service-window)。
- **没有可发送的 `wa_id`。** WhatsApp 通过帐户 ID 标识卡片的联系人；Bird 从每个 E.164 `phone_number` 中推导该 ID，而非接受一个现成的 ID，因此卡片上的按钮永远只会指向卡片上印刷的号码。
- **`vcard` 是只读的。** WhatsApp 在联系人分享的卡片上生成该字段。无法以原始 vCard 文本的形式发送卡片。
- **卡片不是联系人记录。** 发送卡片只是在消息中分享详情；它不会在您的工作区中创建任何内容，收件人是否保存完全是他们自己的操作，对您不可见。

## 后续步骤

- [WhatsApp 服务消息](/docs/guides/whatsapp/message-types)：客服窗口以及所有服务消息共享的模型
- [联系信息请求](/docs/guides/whatsapp/message-types/interactive/contact-info-requests)：向联系人索要号码，而非发送号码
- [接收 WhatsApp 消息](/docs/guides/whatsapp/receiving-whatsapp)：入站消息、媒体和 `whatsapp.received` webhook
- [发送 WhatsApp 消息](/docs/guides/whatsapp/sending-whatsapp)：请求信封、`202` 模型和安全重试

## Related resources

- [Connecting WhatsApp to Bird: from buying a number to a live channel](/learn/whatsapp/connecting-whatsapp-to-bird) (video)
- [What is the 24-hour customer service window on WhatsApp?](/explained/whatsapp/what-is-the-24-hour-customer-service-window) (answer)
- [WhatsApp message builder](/tools/whatsapp-message-builder) (tool)
- [WhatsApp](/products/whatsapp) (product)

[Get an implementation brief](/learn/workspace?topic=whatsapp)
