← Все статьи
Гайд

Звонок WhatsApp создан, но телефон не звонит: диагностика от preparing до соединения

Если создание голосового звонка WhatsApp вернуло 201, но телефон получателя не звонит, сначала определите последний подтверждённый этап. Ответ state: preparing означает, что ссылка для браузера готова, а не что набор уже начался. Повторное создание звонков может затруднить разбор первой попытки.

Это руководство относится к закрытому бета-тестированию исходящих голосовых звонков один на один, которые человек запускает через неофициальный интерфейс UnifyPort. Это не инструкция по Meta WhatsApp Business Calling API. Первичную настройку и полные примеры запросов смотрите в руководстве по интеграции звонков. Здесь мы ищем проблемный этап по данным, которые уже есть в приложении.

1. Определите, что именно подтверждают ваши данные

НаблюдениеЧто подтвержденоЧто не подтверждено
Создание вернуло 201 и preparingСсылка на звонок подготовленаНабор, вызов или соединение
Запрос текущего звонка вернул activeУправляемый звонок сейчас соединёнWebhook дошёл до приложения
Получен call.answeredСоответствующий звонок был соединёнЗаявка поддержки обновлена
Получен call.endedСоответствующий звонок завершёнНулевая длительность означает отсутствие ответа
Запрос текущего звонка вернул data: {}Текущий звонок под управлением UnifyPort не найденРезультат прошлого звонка или занятость мобильного приложения

Прежде чем объединять наблюдения, сверяйте рабочее пространство, account_id и идентификатор звонка. В ответах API это call_id, а в событиях — data.call.id. Другой оператор мог начать другой звонок с того же аккаунта мессенджера.

2. Создание прошло успешно, но вызова нет

Проверьте следующие пункты по порядку, сверяясь с контрактом создания звонка:

  1. Убедитесь, что приложение выбрало нужный авторизованный аккаунт WhatsApp и его runtime_status равен running.
  2. Проверьте сохранённый запрос: to.id должен содержать полученный для этого аккаунта conversation_id, to.type — user, а media_type — voice. Строка с номером телефона не подходит.
  3. Сравните текущее время с возвращённым expires_at. По умолчанию подготовка действует две минуты с момента создания, но сервер может изменить срок. Он не ограничивает длительность уже соединённого звонка.
  4. Убедитесь, что назначенный оператор открыл закрытую одноразовую ссылку join_url и нажал Start call до истечения срока. Одного открытия страницы недостаточно. Доступ к микрофону обязателен, к камере — нет. Выданное разрешение также не доказывает соединение.

Не используйте истёкшую ссылку повторно. Сначала запросите текущий звонок, затем осознанно подготовьте новую попытку. Если проверки пройдены, а вызов всё ещё не подтверждён, сохраните данные запроса и браузера. Не объявляйте причиной телефон получателя, браузер или сеть без подтверждения.

3. Тайм-аут или конфликт оставляет результат неизвестным

Тайм-аут запроса создания означает неизвестный результат, а не доказанное отсутствие созданного звонка. При конфликте сохраняйте фактическое тело ошибки: у разных конфликтов могут быть разные причины. На сервере выполните запрос текущего звонка, который только читает состояние:

curl 'https://api.unifyport.ai/v1/calls/active?account_id=acc_example' \
  -H 'X-Api-Key: <YOUR_API_KEY>'

Для соединённого исходящего голосового звонка возможен такой ответ:

{
  "request_id": "req_example",
  "data": {
    "call_id": "call_example",
    "state": "active",
    "direction": "outbound",
    "media_type": "voice"
  }
}

Если текущего управляемого звонка нет:

{
  "request_id": "req_example",
  "data": {}
}

Запрос также может вернуть preparing, dialing, ringing или connecting; не предполагайте, что каждая попытка проходит все состояния. Этот запрос не восстанавливает потерянную ссылку, не возвращает историю и не определяет, занят ли кто-то из участников в мобильном WhatsApp. Ошибка запроса не равна успешному пустому ответу.

Сопоставьте возвращённый идентификатор со связью звонка и заявки в своём приложении. Не создавайте другой звонок автоматически и не завершайте незнакомый звонок ради освобождения аккаунта. Если результат остаётся неизвестным, уточните его у оператора перед повтором. При намеренном завершении звонка состояния ответа ended и failed оба являются конечными. Само по себе failed не основание постоянно отправлять запрос завершения.

4. Соединение было, но callback отсутствует

Проверяйте путь от допуска к функции до сохранённого состояния приложения:

  • Допуск: is_beta — флаг рабочего пространства только для чтения, который включает поддержка. Подписка с wildcard не даёт доступ к бета-тестированию. Явная подписка на события звонков без допуска возвращает 403 beta_feature_not_enabled.
  • Подписка: в рабочем пространстве с допуском subscribed_events должен содержать нужные имена событий либо *; список также можно оставить пустым или не указывать. Явный список включает только перечисленные события. Проверьте и событие соединения, и событие завершения.
  • Доставка: проверьте настроенные URL и статус конечной точки, журналы доступа получателя и HTTP-ответы. 2xx подтверждает доставку, но не успешное обновление заявки.
  • Обработка: следуйте руководству по доставке и проверке подписи. Если настроен signing_secret, проверяйте X-Device-Signature по X-Device-Timestamp и исходному телу запроса. Отдельно проверьте устранение дублей по id события, сохранение данных и привязку звонка к заявке.

Порядок доставки не гарантируется. Если событие соединения пришло после завершения, сохраните подтверждение соединения, но не возвращайте завершённый звонок в активное состояние интерфейса. Одного отсутствия callback недостаточно, чтобы заключить, что соединения не было.

5. Нулевая длительность и пустой ответ требуют контекста

duration_seconds — время соединения, округлённое вниз до целых секунд. Поэтому ноль не доказывает, что на звонок не ответили. Храните подтверждение соединения вместе с причиной завершения. При синхронной ошибке создания событие завершения может отсутствовать: не оставляйте каждую неудачную попытку в бесконечном ожидании callback.

Рассмотрим условный пример диагностики: оператор запустил подготовленный звонок, запрос текущего звонка показывает соединение, получатель сохранил событие ответа, но заявка всё ещё «ожидает». Далее нужно проверять привязку и обновление состояния в приложении. Повторный звонок не исправит эту запись. Если позднее запрос вернёт пустой результат, он не восстановит недостающую историю; используйте сохранённые события и запросы.

6. Подготовьте данные для дальнейшего разбора

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

Если остаётся неясный этап, передайте запись технической поддержке. Руководство не подразумевает поддержку входящих и групповых звонков, записи, транскрипции, интеграции SIP/PBX или автономных звонков с ИИ.

UnifyPort API

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

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