← Все статьи
Руководство

Как проверить через API, сохранён ли контакт в WhatsApp

Чтобы проверить, сохранён ли человек в списке контактов подключённого аккаунта WhatsApp, вызовите GET /v1/accounts/{account_id}/contacts/membership в UnifyPort, передав возвращённый API контактов LID в contact_id. Значение data.is_in_contacts: false в успешном ответе означает «не сохранён», а не ошибку запроса. Проверяется список подключённого аккаунта, а не наличие вашего номера в адресной книге собеседника.

Главное

  • Используйте LID, возвращённый API контактов в conversation_id; не создавайте его из телефонного номера.
  • Разделяйте три результата приложения: сохранён, не сохранён и неизвестно.
  • Наличие контакта, история переписки, блокировка и разрешение на маркетинговые сообщения — разные вещи.
  • Проверка ничего не изменяет. Добавление контакта должно оставаться отдельным осознанным действием.

Что доказывает проверка сохранённого контакта

В официальной инструкции WhatsApp указано, что удаление контакта не удаляет историю чата. Поэтому наличие переписки не доказывает, что человек по-прежнему сохранён. Там же описано, как получатель карточки может добавить контакт в адресную книгу или написать ему напрямую: передача данных и сохранение контакта — разные операции.

Справочник UnifyPort по проверке контактов отвечает на более узкий вопрос: входит ли этот контакт в список именно подключённого аккаунта?

ВопросПодходящее подтверждение
Сохранён ли человек у подключённого аккаунта?Успешный ответ и is_in_contacts
Сохранил ли собеседник наш номер?Этот метод не даёт ответа
Заблокирован ли человек?Отдельная проверка списка блокировок
Есть ли чат или передавалась ли карточка?Отдельные данные о беседе или сообщении
Может ли приложение связаться с человеком?Независимо установленное разрешение и правила коммуникации

Разницу между записью в адресную книгу и передачей данных объясняет статья Добавить контакт или отправить vCard. Не добавляйте человека только ради удобства проверки: это изменит состояние, которое вы собирались исследовать.

Подготовьте аккаунт и возвращённый LID

UnifyPort предоставляет неофициальный интерфейс для подключённого аккаунта обмена сообщениями. Это не метод WhatsApp Cloud API. В текущей матрице поддержки действий проверка контактов относится к whatsapp, но не к LINE, Telegram, Zalo или отдельному провайдеру whatsapp-protocol.

Храните выбранный аккаунт вместе с контактом. Поля id, provider_user_id и conversation_id в объекте контакта могут различаться. Для этой операции нужен LID, который API контактов возвращает в conversation_id. Сохраняйте его из законного существующего процесса работы с контактами; не приписывайте @lid к номеру телефона.

Если есть только телефонный номер, но нет проверенного возвращённого LID, оставьте проверку недоступной до выяснения соответствия идентификаторов. Этот метод не описан как поиск по произвольному телефонному номеру.

Ниже приведён пример запроса, а не результат выполненного теста. Заполните переменные окружения на сервере из выбранного аккаунта и сохранённого сопоставления контакта. Не передавайте API-ключ в браузер:

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-ключи и не полные записи контактов. Ограничьте доступ операторов к контактам каждого аккаунта средствами самого приложения.

Частые вопросы

Можно ли узнать, сохранил ли собеседник мой номер?

Нет. Проверяется список контактов подключённого аккаунта, а не адресная книга другого человека.

is_in_contacts: false — это ошибка?

В успешном ответе 200 это нормальный отрицательный результат. Отсутствующие данные и неудачный запрос означают неизвестное состояние, а не false.

Можно ли передать JID телефонного номера вместо LID?

Документированный вход для WhatsApp — LID, возвращённый API контактов в conversation_id. Используйте его, а не предполагаемый идентификатор.

Полученная карточка контакта доказывает, что он сохранён?

Нет. Сообщение с карточкой и изменение адресной книги — разные операции. Когда это важно, проверьте наличие контакта отдельно.

Следующий шаг и источники

Реализуйте проверку только для чтения по справочнику проверки контакта. До выпуска проверьте true, false, отсутствие данных, неподдерживаемого провайдера, тайм-аут и смену выбранного контакта во время запроса. Это рекомендуемые проверки, а не отчёт об уже проведённых тестах.

Источники проверены 2026-10-31:

UnifyPort API

Превратите интеграцию сообщений в стабильный продуктовый pipeline.

Начните с отправки через единый API, затем возвращайте входящие сообщения в бизнес-систему стандартными событиями.