← 所有文章
教程

通过 API 检查 WhatsApp 联系人是否已保存

要检查某人是否已保存到已连接 WhatsApp 账号的通讯录,可调用 UnifyPort 的 GET /v1/accounts/{account_id}/contacts/membership,将联系人接口返回的 LID 作为 contact_id。成功响应中的 data.is_in_contacts: false 表示未保存,不是请求失败。它查询的是当前连接账号的通讯录,不能判断对方有没有保存你的号码。

要点

  • 使用联系人接口以 conversation_id 返回的 LID,不要根据手机号拼接。
  • 应用应区分已保存、未保存、无法确认三种结果。
  • 通讯录归属与聊天记录、屏蔽状态、营销发送许可是不同概念。
  • 查询是只读操作;新增联系人必须单独确认。

“联系人已保存”究竟证明什么?

WhatsApp 的官方联系人指南说明,删除联系人不会删除聊天记录。因此,聊天列表里有这个人,不代表通讯录仍保存着对方。该指南也说明,接收者收到联系人分享后,可以选择添加到通讯录或直接发送消息:分享资料与保存联系人不是同一个操作。

UnifyPort 联系人归属查询文档回答的是更窄的问题:此联系人是否属于当前连接账号的通讯录?

问题应依据什么
当前账号是否保存了此人?成功查询及 is_in_contacts
对方是否保存了我们的号码?此接口不提供答案
此人是否被屏蔽?独立的黑名单查询流程
是否存在聊天,或有人分享过名片?独立的会话或消息证据
应用是否可以主动联系此人?独立确认的授权与沟通规则

关于写入通讯录和分享资料的区别,可参阅新增联系人与发送 vCard 对比。不要为了方便查询而先调用新增接口,否则检查前就改变了原本要观察的状态。

准备账号和真实返回的 LID

UnifyPort 为已连接的消息账号提供非官方接口;这里不是 WhatsApp Cloud API。当前渠道动作支持文档将联系人归属查询映射到 whatsapp,不包括 LINE、Telegram、Zalo 或独立的 whatsapp-protocol 渠道。

应将所选账号与联系人一起保存。联系人对象中的 id、provider_user_id 和 conversation_id 可能不同。对于本操作,文档要求使用联系人接口以 conversation_id 返回的 LID。应从合法的既有联系人流程保留该值,不能给手机号加上 @lid 就当作正确标识。

如果应用只有手机号,没有经过核实的返回 LID,应暂时显示无法查询,先解决身份映射。此接口并未被定义为任意手机号查询服务。

以下是未在本文执行过的示例请求。环境变量应来自后端所选账号和已保存的联系人映射,API Key 不得放到浏览器端:

curl --get \
  "https://api.unifyport.ai/v1/accounts/${UNIFYPORT_ACCOUNT_ID}/contacts/membership" \
  -H "X-Api-Key: ${UNIFYPORT_API_KEY}" \
  --data-urlencode "contact_id=${WHATSAPP_CONTACT_LID}"

查询参数编码可正确保留包含 @ 的标识。成功响应包含 data.contact_id 和布尔值 data.is_in_contacts。

展示三种结果,不要只用一个复选框

常见错误是把所有假值或缺失值都转成“未保存”。这样,超时、不支持的渠道或响应格式异常都会被错误解释为否定结果。

下面的 JavaScript 示例只解释已获取的 HTTP 状态和已解析 JSON,不执行网络请求:

function classifyMembership(httpStatus, body) {
  if (httpStatus !== 200) return 'unknown';
  const value = body?.data?.is_in_contacts;
  if (value === true) return 'saved';
  if (value === false) return 'not_saved';
  return 'unknown';
}

这些字符串是应用内部标签,不是额外的 API 响应字段。连接失败或非 JSON 响应,应在调用分类函数前归为无法确认。

观察结果界面状态建议下一步
200 且布尔值为 true已保存展示检查时间
200 且布尔值为 false未保存确有需要时,提供独立且经过授权的新增操作
501 unsupported_by_provider不支持/无法确认检查所选渠道,不自动新增
超时、失败响应或缺少布尔值无法确认保留诊断信息,排查或刷新

保存观察结果时,带上账号、联系人 LID 和应用记录的检查时间。不要让多个消息账号共用一个缓存结论。如果操作员已经切换联系人,应忽略上一请求的迟到结果;旧观察也不能显示成永久保证。

后续操作必须独立

查询结果为否,不等于获得写入许可。操作员确实需要保存此人时,再使用独立的新增联系人接口,保留返回标识,并在需要最新确认时重新检查归属。

同样,“未保存”也不是“已屏蔽”。静音与屏蔽对比解释了这些独立控制。不要因为展示通讯录状态就自动解除屏蔽、发送测试消息或修改通讯录。

失败时保留 HTTP 状态和可用的 request_id,不要记录 API Key 或完整联系人资料。应用自身也应限制哪些操作员可以查看各账号的通讯录。

常见问题

能判断对方是否保存了我的号码吗?

不能。接口检查当前连接账号的联系人列表,不读取对方通讯录。

is_in_contacts: false 是错误吗?

如果来自成功的 200 响应,它是正常的否定结果。缺少数据或请求失败应视为无法确认,而不是 false。

能用手机号 JID 代替 LID 吗?

WhatsApp 文档要求输入联系人接口以 conversation_id 返回的 LID。请使用该值,不要猜测标识。

收到联系人名片就表示已保存吗?

不是。联系人消息和通讯录操作相互独立,需要确认时应查询归属。

下一步与参考资料

依据检查联系人归属文档实现只读控件。上线前测试 true、false、数据缺失、不支持的渠道、超时,以及请求尚未结束时切换联系人。这是建议测试项,并非已执行的测试结果。

资料核对日期:2026-10-31。

UnifyPort API

让消息接入变成一条稳定的产品管线。

先用统一 API 跑通发送,再用标准事件把所有入站消息接回业务系统。