← 所有文章
教學

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) 來源網址
message.file_key已記載的另一種來源方式,不代表可以自行製造 key 或上傳端點
message.caption圖片、影片、文件及檔案的選填說明文字
provider_data.secondsWhatsApp 音訊及影片的選填非負整數時長,單位為秒

WhatsApp 影片時長範圍為 0–4294967295;provider_data.waveform 仍只適用於音訊。不要將接收資料中的 duration_ms 原樣填進秒數欄位。不需要時長資料時,省略即可。

目前訊息能力矩陣未映射 TikTok 音訊及文件/檔案發送,將 X 音訊列為部分支援,並分別列出 whatsapp-protocol 與 whatsapp。統一端點不代表每個渠道有相同的媒體能力或限制。

建立請求前,先準備檔案

以下屬應用程式設計建議,不是額外的平台保證:

  1. 確認操作人員有權使用所選帳戶向目標對話發送內容。群組應使用對話 ID 及類型,不是訊息作者的 ID。
  2. 分別檢查授權狀態及 runtime_status;已授權不等於連線正常。
  3. 將正確檔案放在受控且可存取的來源。瀏覽器登入後能開啟的頁面,不足以證明發送服務能讀取檔案。
  4. 在獨立伺服器環境、不帶瀏覽器 Cookie 測試讀取,確認回傳的是媒體內容,而非 HTML 登入頁或錯誤頁。
  5. 若使用限時 URL,應為預期排隊及讀取時間安排有效期。發送文件未保證統一的擷取期限;預檢成功亦不代表稍後仍可存取。

建議使用 HTTPS、最小存取範圍及應用程式批准的儲存來源。不要將簽署查詢參數或憑證寫入日誌。這些是安全建議,不代表 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 等屬於接收資料,不是完整發送請求。若原網址已過期,請先按下載連結復原指南確認相應接口的復原方式,再決定是否轉發。

按失敗環節排查

現象下一步檢查應避免
本機路徑、相對網址或 data: URL準備完整 HTTP(S) 檔案來源將路徑改名為 file_key
只有自己的瀏覽器能開啟登入依賴、有效期、重新導向及回應內容假設發送端沿用瀏覽器工作階段
unsupported_message_type渠道與媒體類型組合重複相同請求
provider_not_ready授權及運行狀態未診斷便重新授權
請求逾時保留發送操作記錄,調查不確定結果自動重發而可能產生重複訊息
回應為 accepted保存回傳識別碼,另查支援的送達證據立即顯示「已送達」或「已讀」

按錯誤參考的機器可讀錯誤分支處理,不要猜測描述文字。保留 request_id 供排查,但不要當作去重憑證;請求追蹤指南說明了這個邊界。

處理回條時,查閱事件文件及渠道事件矩陣,驗證 webhook 簽署,並容忍重複及次序錯置。並非每個渠道都有所有回條,因此缺少確認應保留為未知,而不是觸發再次發送。

驗收檢查與常見問題

正式啟用前建議測試:可存取檔案、已過期來源、登入頁回應、不支援的渠道/類型組合、帳戶斷線及發送回應遺失。本文不聲稱已執行這些線上測試。

這個 JSON 請求可以直接上傳本機檔案嗎?

已記載的媒體請求使用 URL 或檔案 key 來源。本文不提供或承諾 multipart 上傳端點。請透過獲准儲存流程託管檔案,再提供可存取 URL。

Telegram file_id 可以當作 file_key 嗎?

文件沒有建立這種對應。請分開處理 Telegram 原生檔案識別碼與 UnifyPort 來源欄位。

accepted 表示對方收到檔案了嗎?

不是。它表示請求已接受,而不是送達或已讀回條。

下一步與參考資料

按發送圖片和檔案指南,先用一個獲准測試對話及受控檔案來源確認流程,再啟用排隊或自動發送。

參考資料核對日期:2026-10-09。

UnifyPort API

令訊息接入變成一條穩定嘅產品管線。

先用統一嘅 API 跑通發送,再用標準事件將所有入站訊息接返去業務系統。