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.seconds | WhatsApp 音訊和影片的選填非負整數時長,單位為秒 |
WhatsApp 影片時長範圍為 0–4294967295;provider_data.waveform 仍限音訊使用。不要直接把接收資料中的 duration_ms 填進秒數欄位。不需要時長中繼資料時,省略即可。
目前訊息能力矩陣未映射 TikTok 音訊及文件/檔案傳送,將 X 音訊標示為部分支援,並分別列出 whatsapp-protocol 與 whatsapp。統一端點不代表每個管道有相同的媒體能力或限制;LINE 與其他管道也應各別檢查。
建立請求前,先準備檔案
以下是應用程式設計建議,不是額外的平台保證:
- 確認操作人員有權透過所選帳號傳送至目標對話。群組對話應使用對話 ID 和類型,不是訊息作者的 ID。
- 分別檢查授權狀態與
runtime_status;已授權不等於連線正常。 - 將正確檔案置於受控且可存取的來源。瀏覽器登入後能開啟的頁面,不能證明傳送服務取得到檔案。
- 在獨立伺服器環境、不帶瀏覽器 Cookie 測試讀取,確認回傳的是媒體內容,而非 HTML 登入頁或錯誤頁。
- 若使用限時 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。
讓訊息接入變成一條穩定的產品管線。
先用統一 API 跑通傳送,再用標準事件把所有入站訊息接回業務系統。