踩坑實錄

Meta API 串接的 8 個坑:官方文件沒寫的那些

我想做的事很單純:讓程式自動把一篇文章發到 Facebook 粉專、Instagram、Threads。官方文件寫了幾個步驟,看起來一小時能搞定。實際花了五小時——而真正擋住我的八個問題,沒有一個寫在文件裡。

2026/08/08 | 環境:Meta 開發者後台的新版 App 建立流程(use case 導向的那一版)

一個核心觀念:介面的錯誤訊息會騙人,HTTP status code 不會

這五小時裡最貴的一課:Meta 後台跳出來的紅色提示寫著「無法儲存表單,請確認你輸入的所有資訊皆正確無誤」——這句話會讓你反覆檢查自己填的東西,懷疑是不是網址格式錯了、是不是少填哪一欄。

我照著這個提示改了六、七次都沒用。打開瀏覽器開發者工具的 Network 分頁,看那個儲存動作實際打出去的請求,才發現真相:

POST /apps/{app_id}/async/threads-login/setting/save/  →  404

後端根本回 404,不是驗證錯誤。「請確認輸入正確」是前端不管收到什麼錯誤都套用的通用文案。如果我一開始就看 status code,可以省下至少一小時。

所以第一個可遷移的習慣:任何後台「存了沒反應/存不進去」的情況,先開 Network 看實際 status code 再動手改設定。400 是你的錯,404/500 是對方的事——這兩件事的處理方式完全相反,錯誤訊息卻長得一樣。

坑 1|Threads 設定存不了,後端回 404

症狀:Threads use case 的「重新導向回呼網址」填好按儲存,跳通用錯誤,重整後欄位是空的。

原因:這個表單要求三個回呼網址欄位全部填滿才會過——「重新導向回呼網址」「解除安裝回呼網址」「刪除回呼網址」。只填第一個(另外兩個是選填的樣子)就會靜默失敗回 404。

解法:三欄都填。本機測試時三欄可以填同一個網址,Meta 不會驗證它們是否真的不同。

坑 2|「應用程式網域」不接受 localhost

舊教學都說在「應用程式設定 → 基本資料 → 應用程式網域」填 localhost。現在填會被擋下:「必須直接在名稱後包含頂層網域(例如「.com」或「.org」)」

解法:填你真正的網域就好(例如 example.com)。本機開發的 localhost 回呼不需要登記在這裡——見下一坑。

坑 3|Facebook Login 的 localhost 回呼根本不用登記

我花了時間試著把 http://localhost:8080/callback 填進「有效的 OAuth 重新導向 URI」,一直存不住。重新整理後才看到欄位旁邊的小提示:

http://localhost 重新導向只會在開發模式中自動啟用,不需要在此新增。

解法:App 在開發模式下,http://localhost 的回呼自動放行,別浪費時間登記。但 Threads 不吃這套——Threads 強制 HTTPS,連 localhost 也要走 https://,而且必須照坑 1 的方式登記。同一個 App 底下兩套規則,這是最容易搞混的地方。

坑 4|Invalid Scopes: pages_read_user_content(你根本沒要這個權限)

症狀:授權頁直接報錯,說 pages_read_user_content 是無效的 scope。但我的授權請求裡從來沒有這個 scope,App 的權限清單裡它也是未啟用狀態。

原因:加了「管理粉絲專頁」use case 會自動掛上 Facebook Login for Business,而它在沒有明確設定的情況下會自己注入這個 scope 去檢查——一個你沒要、卻會擋住你的幽靈權限。

解法(反直覺):到 use case 的權限清單裡,把這個報錯的權限「新增」進去。它從「未啟用」變成「可供測試」之後,授權頁就正常了。錯誤訊息叫你拿掉,實際要做的是加上去。

坑 5|改用 config_id 之後,授權頁直接 HTTP 500

官方對 Facebook Login for Business 的建議是:不要傳 scope,改用後台建好的 Login Configuration ID。我照做,建了一個 configuration,把 config_id 傳進 OAuth dialog——

GET /v25.0/dialog/oauth?...&config_id={config_id}  →  500

整頁變成 Facebook 的通用錯誤頁「Sorry, something went wrong」。等了十幾分鐘讓設定生效、重試,依然 500。查遍社群找不到同樣情況的回報,官方 troubleshooting 文件列的三種已知錯誤也不包含 500。

解法放棄 config_id,回頭走傳統的 scope 參數。官方文件自己也註明 scope「仍可傳」。搭配坑 4 的修法之後,scope 這條路是通的。有時候正確答案是繞過官方推薦的新路徑。

坑 6|/me/accounts 回空清單,但你明明是粉專管理員

症狀:授權成功、拿到 user token,接著呼叫 GET /me/accounts 要取粉專清單和 Page token,回來是空陣列。反覆確認自己確實是粉專管理員。

原因:粉專如果掛在商家資產管理組合(Business Portfolio)底下(新版建立 App 時會問你要不要連結,選了就會掛上去),一般的 pages 權限看不到它。

解法:在 scope 清單裡加上 business_management。加完重跑授權,粉專就出現了,Page token 和 Instagram business account ID 一次到手。

坑 7|Threads 的測試人員是完全獨立的一份名單

症狀:Threads 授權頁回 {"error_message":"Invalid Request: The user has not accepted the invite to test the app.","error_code":1349245}。而我就是這個 App 的管理員。

原因:App 管理員身分不會自動涵蓋 Threads。Threads API 有自己的「Threads 測試人員」名單,藏在「應用程式角色 → 角色 → 更多」下拉選單裡(不是主要的角色清單)。

解法:在那裡新增你的 Threads 帳號 → 對方會收到邀請 → 必須用該 Threads 帳號本人去接受(在 Threads App 個人檔案的「網站權限」區塊)。狀態從「待確認」消失才算數。

坑 8|邀請接受了,還是同一個錯誤

接受邀請之後重跑,還是回一模一樣的 error_code: 1349245。這時候很容易誤判成「邀請沒生效,再等等」——我差點就這樣結案了。

真正原因:邀請是在手機 App 上接受的,但跑 OAuth 的是電腦瀏覽器,而電腦上的 Threads 網頁版登入的是另一個帳號。錯誤訊息說的是實話——「這個使用者沒有接受邀請」,只是「這個使用者」指的是瀏覽器裡當下登入的那個,不是你以為的那個。

解法:確認執行授權的那個瀏覽器,登入的就是被邀請的帳號本人。改對之後一次就過。

可複製的排查順序

如果你正卡在 Meta API 的某一步,照這個順序排查會比亂改設定快:

  1. 先看 Network 的 status code,別看畫面上的錯誤文案。4xx 檢查自己,5xx 換路徑或等平台。
  2. 報錯提到某個權限,先試著把那個權限加進去,而不是想辦法移除它。
  3. 官方推薦的新路徑走不通就走舊的(config_id ↔ scope),文件通常兩種都還支援。
  4. 拿到 token 卻查無資產,先想「這個資產是不是掛在商家組合底下」,補 business_management
  5. 權限/角色類的錯誤,確認「執行授權的那個瀏覽器 session」登入的帳號,跟你在後台加的帳號是同一個。

一句話總結

平台官方文件描述的是理想路徑,改版後的實際路徑靠社群口耳相傳——遇到「存了沒反應」先看 HTTP status code,因為介面的錯誤文案會騙你,網路請求不會。