Звонок 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. Создание прошло успешно, но вызова нет
Проверьте следующие пункты по порядку, сверяясь с контрактом создания звонка:
- Убедитесь, что приложение выбрало нужный авторизованный аккаунт WhatsApp и его
runtime_statusравенrunning. - Проверьте сохранённый запрос:
to.idдолжен содержать полученный для этого аккаунтаconversation_id,to.type—user, аmedia_type—voice. Строка с номером телефона не подходит. - Сравните текущее время с возвращённым
expires_at. По умолчанию подготовка действует две минуты с момента создания, но сервер может изменить срок. Он не ограничивает длительность уже соединённого звонка. - Убедитесь, что назначенный оператор открыл закрытую одноразовую ссылку
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 или автономных звонков с ИИ.
Превратите интеграцию сообщений в стабильный продуктовый pipeline.
Начните с отправки через единый API, затем возвращайте входящие сообщения в бизнес-систему стандартными событиями.