← 所有文章
教學

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。統一端點不代表每個管道有相同的媒體能力或限制;LINE 與其他管道也應各別檢查。

建立請求前,先準備檔案

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

  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 跑通傳送,再用標準事件把所有入站訊息接回業務系統。