Перенос чатов WhatsApp между ярлыками: безопасный сценарий API
Чтобы перенести чат WhatsApp из одного рабочего ярлыка в другой через UnifyPort, выполните две операции: добавьте целевой ярлык, проверьте результат и только затем снимите исходный. Атомарный перенос в публичной документации не предусмотрен. Сохраняйте остальные ярлыки, а незавершённый переход показывайте явно. Не удаляйте сам ярлык и не считайте тайм-аут доказательством того, что изменений не было.
Главное
action: "remove"снимает ярлык с выбранных диалогов. Удаление самого ярлыка — отдельная операция.- Несколько ярлыков могут существовать одновременно: они не обеспечивают единственного ответственного или единственный этап.
- Добавление перед снятием помогает сохранить видимость чата, но временно оставляет оба ярлыка.
- Основную запись о назначении и ходе перехода храните в приложении, а не выводите только из ярлыков.
Определите переход, а не замену всех ярлыков
В справке WhatsApp о ярлыках описаны организация чатов и применение нескольких ярлыков к одному чату. Там также указано, что ярлыки постепенно заменяются списками. Такая терминология интерфейса не переименовывает поле label_id в UnifyPort и не означает, что каждому списку приложения соответствует API.
Рассмотрим условный сценарий: у чата есть ярлыки «Ожидает» и «VIP», а оператор переводит его в «В работе». Нужны добавление «В работе» и снятие «Ожидает», при этом «VIP» остаётся. Это не замена всех ярлыков одним новым.
В июньском обновлении API представлены операции с ярлыками. Для передачи работы важно различать их объекты:
| Намерение | Операция | Объект |
|---|---|---|
| Создать или переименовать категорию | Создание или обновление ярлыка | Определение ярлыка |
| Добавить целевой ярлык | Связь action: "add" | Выбранные диалоги под этим ярлыком |
| Снять исходный ярлык | Связь action: "remove" | Выбранные диалоги под этим ярлыком |
| Упразднить категорию | Удаление ярлыка | Сам ярлык, а не связь одного чата |
Не заменяйте снятие ярлыка с одного диалога удалением категории: её могут использовать другие чаты.
Подготовьте две операции
Получите исходный и целевой идентификаторы через каталог ярлыков выбранного аккаунта обмена сообщениями. Пройдите пагинацию: название служит для отображения, а не является надёжным ключом идентичности. Если целевой ярлык нужно создать, используйте создание или обновление ярлыка и сохраните возвращённый data.id.
Определите conversation_id чата в том же аккаунте. Не подставляйте вместо него название ярлыка, отображаемое имя контакта или ID сообщения. Проверьте матрицу поддержки операций: эти операции сейчас поддерживаются для whatsapp, но не для LINE, Telegram, Zalo или отдельного провайдера whatsapp-protocol.
Справочник изменения связей ярлыка определяет POST /v1/accounts/{account_id}/conversations/labels с полями label_id, action и непустым массивом conversation_ids.
Этот серверный JavaScript выполняет одну операцию, намеренно не автоматизируя весь переход. Передавайте реальные ID, выбранные бэкендом, и API-ключ из защищённого хранилища. Это иллюстрация, а не протестированный production-клиент.
async function changeLabelMembership({
apiKey, accountId, labelId, conversationIds, action
}) {
const validId = value => typeof value === 'string' && value.trim() !== '';
if (!validId(accountId) || !validId(labelId) ||
!Array.isArray(conversationIds) || conversationIds.length === 0 ||
!conversationIds.every(validId) || !['add', 'remove'].includes(action)) {
throw new Error('Select an account, label, conversations, and action');
}
const response = await fetch(
`https://api.unifyport.ai/v1/accounts/${encodeURIComponent(accountId)}/conversations/labels`,
{
method: 'POST',
headers: { 'X-Api-Key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({
label_id: labelId,
action,
conversation_ids: [...new Set(conversationIds)]
})
}
);
const result = await response.json();
return { httpStatus: response.status, result };
}
Для первого вызова используйте целевой ID и add, для последующего — исходный ID и remove с тем же чатом. Локально отклоняйте переход с одинаковыми исходным и целевым ID. Проверяйте HTTP-статус и данные ответа: завершение fetch без исключения ещё не означает успех. Документированный успешный ответ содержит затронутые label_id, action и conversation_ids.
Проверяйте состояние между добавлением и снятием
Следующие шаги — рекомендации для приложения, а не гарантия транзакции со стороны UnifyPort:
- Сохраните аккаунт, диалог, исходный и целевой ярлыки. Проверьте право оператора менять назначение.
- Добавьте целевой ярлык. Запишите ответ и
request_id, но не API-ключ. - Получите целевое представление через список диалогов с явным
label_id. Убедитесь, что выбранный чат появился, прежде чем снимать исходный ярлык. - Снимите только исходный ярлык. Независимые ярлыки, например VIP, сохраните.
- Сверьте оба представления. Если наблюдения не соответствуют намерению, оставьте работу незавершённой.
Не проверяйте целевой ярлык через список без фильтра. По документированному контракту WhatsApp отсутствие label_id выбирает только отмеченные особым вниманием диалоги. Руководство по отсутствующим чатам и фильтрам ярлыков объясняет эту границу и пагинацию. Отсутствие на первой странице не доказывает отсутствие вообще; ошибка чтения не равна пустому результату. Постраничное чтение в реальном времени не гарантирует неизменяемый снимок.
| Наблюдаемая связь | Значение для этого перехода | Рекомендация |
|---|---|---|
| Только исходный ярлык | Целевой пока не наблюдается | Сохранить исходный и проверить добавление |
| Оба ярлыка | Промежуточное состояние или чужое изменение | Уточнить актуальное намерение перед снятием исходного |
| Только целевой | Наблюдается нужная комбинация | Завершить локальную запись, если назначение по-прежнему совпадает |
| Ни одного или чтение неполное | Состояние не выяснено | Сохранить локальную работу и расследовать |
Восстанавливайте состояние, не повторяя устаревшие намерения
Последовательно выполняйте изменения одного диалога в своём приложении и отбрасывайте устаревшие задания перед отправкой. Если другой оператор уже изменил назначение, не завершайте старый переход автоматически. Локальная сериализация не блокирует все связанные клиенты, поэтому внешние изменения нужно сверять отдельно.
При тайм-ауте добавления сохраните исходный ярлык и проверьте целевой перед следующим решением. При неопределённом результате снятия прочитайте оба представления до повторного запроса. Не делайте автоматический «откат» снятием целевого ярлыка: другой оператор уже мог начать на него полагаться.
Публичный справочник не обещает атомарность двух вызовов, выполнение всего пакета по принципу «всё или ничего», предусловие по версии или специальный webhook об изменении ярлыка. Даже при пакетной обработке храните прогресс отдельно для каждого диалога. set_label_members_failed документирован для серверной или вышестоящей ошибки; unsupported_by_provider обозначает отсутствие поддержки, а не повод бесконечно повторять запрос.
Вопросы и ответы
Добавление нового ярлыка снимает старый?
Нет. API предоставляет явные действия добавления и снятия. Обрабатывайте каждую связь независимо.
Можно ли ярлыками обеспечить единственного ответственного?
Этот контракт такой гарантии не даёт. Храните ответственного и права в приложении, а ярлыки используйте как отражение решения на стороне провайдера.
Подтвердит ли conversation.updated завершение перехода?
Не рассчитывайте на это. Документированные настройки включают отключение уведомлений, архивирование, закрепление и прочтение, а не гарантированную квитанцию об изменении ярлыков.
Это официальная операция WhatsApp Cloud API?
Нет. Это эндпоинты неофициального интерфейса UnifyPort для подключённого аккаунта. Справка WhatsApp объясняет пользовательскую функцию, а не данный контракт API.
Следующий шаг и источники
Начните со справочника добавления и снятия ярлыка с диалогов. В контролируемом аккаунте проверьте обычный переход, ошибку добавления, тайм-аут снятия, конкурирующие изменения, пагинацию и сохранение постороннего ярлыка. Только затем включайте массовые переходы. Это предлагаемые проверки, а не отчёт об уже выполненных тестах.
Источники проверены 2026-10-14:
Превратите интеграцию сообщений в стабильный продуктовый pipeline.
Начните с отправки через единый API, затем возвращайте входящие сообщения в бизнес-систему стандартными событиями.