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

Отправка медиа через UnifyPort: проверка URL и доставки

Для отправки изображения, видео, аудио или документа через UnifyPort используйте POST /v1/messages, поддерживаемый message.type и хотя бы один непустой источник: message.url, message.file_url или message.file_key. URL должен быть абсолютным HTTP(S)-адресом. Имя локального файла не является доступным URL, а ответ со status: accepted не подтверждает получение файла адресатом.

Главное

  • Проверяйте поддержку формата для канала выбранного аккаунта обмена сообщениями.
  • Начните с одного явно заданного доступного URL; не угадывайте приоритет нескольких источников.
  • Исходящий объект message отличается от входящего data.message.attachments[].
  • Проверяйте доступ к файлу, валидацию запроса, подключение аккаунта и доставку отдельно.

Сначала выберите контракт отправки

Неофициальный интерфейс UnifyPort использует контракт отправки медиа. Это не Telegram Bot API и не LINE Messaging API. Например, документация Telegram по отправке файлов описывает идентификаторы файлов, HTTP URL и multipart-загрузку для собственных методов. Из этого не следует, что UnifyPort принимает Telegram file_id в качестве file_key или поддерживает тот же запрос загрузки.

ПолеЧто установлено документацией UnifyPort
message.typeТипы включают image, video, audio, document, file; поддержку канала нужно проверять отдельно
message.url или message.file_urlНепустой абсолютный HTTP(S) URL источника
message.file_keyДокументированная альтернатива, но не основание придумывать ключ или endpoint загрузки
message.captionНеобязательная подпись для изображения, видео, документа и файла
provider_data.secondsНеобязательная длительность аудио и видео WhatsApp: неотрицательное целое число секунд

Для видео WhatsApp допустим диапазон длительности 0–4294967295. provider_data.waveform предназначен только для аудио. Не копируйте входящее значение duration_ms в поле секунд без преобразования. Если длительность не нужна, не передавайте её вместо угадывания значения.

Текущая матрица поддержки сообщений не предусматривает отправку аудио и документов/файлов в TikTok, отмечает аудио X как частично поддерживаемое и разделяет whatsapp-protocol и whatsapp. Общий endpoint не гарантирует одинаковых возможностей и ограничений для всех каналов.

Подготовьте файл до формирования запроса

Это рекомендации по архитектуре приложения, а не дополнительные гарантии платформы:

  1. Убедитесь, что оператор вправе отправлять сообщения через выбранный аккаунт в выбранный диалог. Для группы используйте ID и тип диалога, а не ID автора сообщения.
  2. Проверьте авторизацию и runtime_status отдельно: авторизованный аккаунт не обязательно подключён.
  3. Разместите нужный файл в контролируемом доступном источнике. Страница, открывающаяся после входа в браузере, не доказывает, что отправляющий сервис получит файл.
  4. Проверьте получение из отдельного серверного окружения без браузерных cookie. Убедитесь, что ответ содержит нужные медиа, а не HTML-страницу входа или ошибки.
  5. Если URL имеет срок действия, учитывайте ожидаемое время в очереди и последующее получение. Контракт не обещает единого предельного срока скачивания; успешная предварительная проверка не гарантирует доступность позже.

Предпочитайте HTTPS, минимально необходимый доступ и одобренное приложением хранилище. Не записывайте подписанные параметры URL и секреты в обычные логи. Это рекомендации по безопасности, а не утверждения о недокументированных сетевых фильтрах UnifyPort.

Сформируйте запрос с URL

Эта JavaScript-функция создаёт тело запроса из выбранного аккаунта, диалога и разрешённого URL. Она не загружает файл и не проверяет его доступность по сети. До вызова проверьте права оператора и поддержку канала.

function buildMediaRequest({ accountId, conversation, type, url, caption }) {
  const types = new Set(['image', 'video', 'audio', 'document', 'file']);
  if (!accountId || !conversation?.id || !conversation?.type) {
    throw new Error('Account and conversation are required');
  }
  if (!types.has(type)) throw new Error('Unsupported media type');

  const source = new URL(url);
  if (!['http:', 'https:'].includes(source.protocol) ||
      source.username || source.password) {
    throw new Error('Use an approved HTTP(S) media source');
  }

  const message = { type, url: source.href };
  if (caption !== undefined) {
    if (type === 'audio' || typeof caption !== 'string') {
      throw new Error('Caption is not valid for this request');
    }
    message.caption = caption;
  }

  return {
    account_id: accountId,
    to: { id: conversation.id, type: conversation.type },
    message,
  };
}

Отправьте полученный JSON в POST /v1/messages с серверной аутентификацией через X-Api-Key и Content-Type: application/json. Функция намеренно задаёт только message.url. Документация требует хотя бы один источник, но не определяет приоритет конфликтующих источников.

Не вставляйте входящий объект вложения непосредственно в тело отправки. В руководстве по входящим медиа описаны attachments[].type, url, mimetype и сопутствующие данные: это поля получения, а не полный исходящий запрос. Если исходная ссылка уже истекла, сначала определите подходящий способ восстановления по руководству по ссылкам на скачивание, а затем решайте вопрос пересылки.

Найдите этап сбоя

НаблюдениеЧто проверитьЧего избегать
Передан локальный путь, относительный URL или data: URLПодготовьте абсолютный HTTP(S) URLПереименовывать путь в file_key
URL работает только в вашем браузереАвторизацию, срок действия, перенаправления и реальные байты ответаСчитать, что браузерная сессия доступна отправителю
unsupported_message_typeКанал и тип медиаПовторять неизменный запрос
provider_not_readyАвторизацию и состояние подключенияЗапускать повторную авторизацию без диагностики
Тайм-аут запросаСохраните исходящую операцию и разберите неопределённый результатАвтоматически отправлять ещё раз с риском дубля
Ответ acceptedСохраните идентификаторы; отдельно проверьте поддерживаемые подтверждения доставкиСразу показывать «доставлено» или «прочитано»

Справочник ошибок определяет машиночитаемые коды: используйте их, а не предположения по тексту сообщения. Сохраняйте request_id для диагностики, но не как токен дедупликации. Эту границу объясняет руководство по трассировке запросов.

При обработке подтверждений сверяйтесь со справочником событий и матрицей каналов. Проверяйте подпись webhook и учитывайте дубликаты и нарушение порядка событий. Не каждый канал выдаёт каждый вид подтверждения. Отсутствие подтверждения оставляет результат неизвестным, а не разрешает повторную отправку.

Приёмочные проверки и FAQ

До запуска предусмотрите тесты доступного файла, истёкшего URL, страницы входа вместо файла, неподдерживаемой пары канал/тип, отключённого аккаунта и потери ответа отправки. Здесь не заявляется, что эти проверки уже выполнены в реальной среде.

Можно ли напрямую загрузить локальный файл этим JSON-запросом?

Документированный запрос использует URL или файловый ключ. Статья не устанавливает наличие multipart-endpoint. Разместите файл через разрешённый процесс хранения и используйте доступный URL.

Можно ли передать Telegram file_id как file_key?

Такая совместимость не документирована. Не смешивайте нативные идентификаторы Telegram с полями источника UnifyPort.

Означает ли accepted, что получатель получил файл?

Нет. Это принятие запроса, а не подтверждение доставки или прочтения.

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

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

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

UnifyPort API

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

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