僅在使用時載入搜尋。在下方瀏覽所有類別。

伺服器 API 參考資料

SosoAPI 發布 API:身分驗證、請求和結果

以每個目標一份排程貼文建置伺服器端發布整合。此參考涵蓋於 2026 年十月 20 日 審核的發布 API 契約。範例包含預留位置,不會在此頁面執行。

閱讀 Markdown

由 SosoAPI 團隊檢閱 ·

1. 從伺服器進行驗證

在「SosoAPI App → 設定 → 代理程式與 API 存取權」建立 API key。於伺服器環境儲存為 SOSOAPI_API_KEY。請求使用 Authorization: Bearer <your-key> 及 Content-Type: application/json。切勿將 key 嵌入網站、行動應用程式套件、URL 或公開儲存庫。

以下所有端點皆使用 POST 與 JSON 主體。Keys 與委派代理程式授權受其能力、允許的 Workspaces 及擁有者目前成員資格限制。讀取需要 agent:operate 及至少 viewer 權限;發布變更需要 agent:publish 及至少 editor 權限。授權無法擴大擁有者的權利。

使用應用程式的目前工作空間和已連結帳號,或呼叫 /identity-api/workspace/list 和 /identity-api/user/social-accounts/list 查找您獲准使用的 ID。不要猜測客戶的工作空間或帳號 ID。

// Node.js 20+; run only on your server.
const apiKey = process.env.SOSOAPI_API_KEY;
if (!apiKey) throw new Error("Set SOSOAPI_API_KEY on your server");
const apiBase = "https://gqeshlawtcexsapabaui.supabase.co/functions/v1";

async function sosoPost(path, body) {
  const response = await fetch(apiBase + path, {
    method: "POST",
    headers: {
      Authorization: "Bearer " + apiKey,
      "Content-Type": "application/json"
    },
    body: JSON.stringify(body)
  });
  const result = await response.json();
  if (!response.ok) {
    const requestId = result.request_id ?? response.headers.get("x-request-id");
    // Handler errors use code/message; schema-validation 400s instead use
    // success:false and error:{name:"ZodError",message:...}.
    // Preserve status, available code and requestId in server diagnostics.
    // Never log the key or an Authorization header.
    throw new Error("SosoAPI " + response.status + " (" +
      (requestId ?? "no request id") + ")");
  }
  return result;
}

2. 發布端點映射

這些路徑相對於伺服器輔助函式使用的 API 基底網址。請取得排程貼文詳細資料,以取得目前版本、可用操作與發布結果。

排程貼文端點;所有請求皆為 POST
路徑請求回應與邊界
/studio-api/scheduled-posts/listworkspace_id;選填 project_id、status、時間配對、limit、cursor。posts、next_cursor、returned_count。限定於工作空間的讀取。
/studio-api/scheduled-posts/getid.post、delivery、actions、attempts、outcomes。在此讀取目前 version。
/studio-api/scheduled-posts/eligibilityworkspace_id、targets;選填 include_quota。目標和選填配額。唯讀預檢,不是預留。
/studio-api/scheduled-posts/createworkspace_id、確切帳號、provider_payload、content、scheduled_at、idempotency_key。post 與 deduped。新排程為 201;相符重播為 200。
/studio-api/scheduled-posts/bulk-createworkspace_id 與 1–50 個 targets,各自具有自己的 idempotency_key。batch_id、successes、failures。至少一項成功時為 201;無任何成功時為 422。請檢查兩個陣列。
/studio-api/scheduled-posts/updateid、expected_version、patch;選填相符的 provider_payload。post。過期版本會被拒絕;目標不可更改。
/studio-api/scheduled-posts/publish-nowid 與 expected_version。post。請求立即執行;不證明已發布。
/studio-api/scheduled-posts/retryid、expected_version;選填的未來 scheduled_at。post。僅限失敗、以證據為門檻的復原;絕不盲目重送。
/studio-api/scheduled-posts/cancelid 與 expected_version。post。取消尚未發布的工作;遠端取消可能仍處於待處理狀態。
/studio-api/scheduled-posts/deleteid 與 expected_version。post。機器呼叫端無法刪除已發布的平台內容。
/studio-api/scheduled-posts/withdraw-deleteid 與 expected_version。post。撤回已停止、僅供驗證的 Instagram Login 刪除請求;保留平台內容。

3. 在保留範圍的前提下列出和分頁

limit 預設為 50,接受 1–200。選填 status 為 scheduled、publishing、published、failed、expired、needs_reschedule、cancelled 或 deleted 之一。scheduled_from 和 scheduled_to 必須一同提供,格式為帶偏移量的 ISO-8601 時刻;結束時間必須晚於開始時間。

next_cursor 為 null 或含 scheduled_at 和 id 的物件。將整個物件作為 cursor 連同相同工作空間和篩選條件傳回。此端點不接受 page、offset、platform 或 social_account_id 篩選。

await sosoPost("/studio-api/scheduled-posts/list", {
  "workspace_id": "<workspace-uuid>",
  "limit": 50
});
const first = await sosoPost("/studio-api/scheduled-posts/list", {
  workspace_id: "<workspace-uuid>", limit: 50
});
if (first.next_cursor) {
  const next = await sosoPost("/studio-api/scheduled-posts/list", {
    workspace_id: "<workspace-uuid>", limit: 50, cursor: first.next_cursor
  });
  // Consume next.posts; continue only while next_cursor is not null.
}

4. 驗證並建立一則已審核貼文

將所有預留位置替換為授權範圍內的值和未來時間。執行此範例會排程一則真實的 Threads 文字貼文。呼叫建立操作前,請獲得本人對帳號、內容和時間的確認。

設定 provider_payload.platform 及該平台的 publish_options。伺服器會確認兩者與所選帳號相符。可加入 project_id 記錄貼文來源;專案不會授予發布存取權,也不會控制排程。

建立請求欄位與預設值
欄位契約
workspace_id / social_account_id已授權 Workspace 及確切目標所需的 UUID。
provider_payload必填平台判別欄位及平台專屬 publish_options。
scheduled_at / display_timezone必填的帶偏移量 ISO-8601 時刻;有效的 IANA 顯示時區,預設為 UTC。
idempotency_key必填的去除首尾空白字串,8–160 個字元,對此次意圖保持不變。
caption / hashtagscaption 可為 null,最多 5,000 個字元;預設為 null。hashtags 預設為 [];最多 100 個字串,每個 100 個字元。平台限制可能更嚴格。
media預設 [];最多 20 個已登記媒體參照。各參照具有 kind image/video 及標準 url;請加入其已就緒的 asset_id。平台規則可能更嚴格。
link_url選填 URL 或 null。目標與貼文類型必須支援此欄位。
local_scheduled_at / schedule_dst_disambiguation選填配對:不含時差的本地時間,以及 exact/earlier/later。必須兩者皆提供或皆省略,且與預期時間點及時區相符。
expires_at / automatic_retry_enabled選填的 scheduled_at 之後的到期時間;null 表示不過期。自動重試預設為 true,仍受平台安全規則約束。
project_id / source_ref選填且可為 null 的 Project UUID 及呼叫端來源物件。兩者均不改變權限。
await sosoPost("/studio-api/scheduled-posts/eligibility", {
  "workspace_id": "<workspace-uuid>",
  "include_quota": true,
  "targets": [
    {
      "social_account_id": "<threads-account-uuid>",
      "media": [],
      "provider_payload": {
        "platform": "threads",
        "publish_options": {
          "post_type": "TEXT"
        }
      },
      "draft": {
        "caption": "A reviewed update from our team.",
        "hashtags": [],
        "scheduled_at": "<future-ISO-8601-instant-with-offset>",
        "display_timezone": "Asia/Hong_Kong"
      }
    }
  ]
});
await sosoPost("/studio-api/scheduled-posts/create", {
  "workspace_id": "<workspace-uuid>",
  "social_account_id": "<threads-account-uuid>",
  "caption": "A reviewed update from our team.",
  "hashtags": [],
  "media": [],
  "provider_payload": {
    "platform": "threads",
    "publish_options": {
      "post_type": "TEXT"
    }
  },
  "scheduled_at": "<future-ISO-8601-instant-with-offset>",
  "display_timezone": "Asia/Hong_Kong",
  "idempotency_key": "<stable-key-for-this-one-intent>"
});

5. 查看結果並安全取消

建立會回傳 { post, deduped }。清單會回傳 { posts, next_cursor, returned_count }。讀取會回傳 { post, delivery, actions, attempts, outcomes }。貼文包含 id、status、version、destination、schedule,以及可用的平台身分/永久連結;delivery 與 actions 說明目前進度與允許的下一步。

status 為 scheduled 或 publishing 的貼文仍待處理。status 為 published 的終端發布結果才確認已發布,並包含該貼文可取得的平台證據;可能缺少永久連結。如果用戶端中斷連線或回應延遲,請先讀取既有貼文再回報結果。

取消前,先取得貼文詳細資料並傳入目前的數值 version。SosoAPI 取消平台持有的排程時,結果可能為 cancellation_pending。取消排程不會刪除已發布貼文。

await sosoPost("/studio-api/scheduled-posts/get", {
  "id": "<scheduled-post-uuid>"
});
const detail = await sosoPost("/studio-api/scheduled-posts/get", {
  id: "<scheduled-post-uuid>"
});
// Run only after the person confirms cancelling this unpublished post.
await sosoPost("/studio-api/scheduled-posts/cancel", {
  id: detail.post.id, expected_version: detail.post.version
});

6. 冪等性、衝突與寫入結果不明

重複同一建立請求時,使用相同的 idempotency_key。相符的重播會回傳現有貼文,且 deduped=true。重複使用該 key 但更改內容會導致衝突。這可防止在 SosoAPI 中重複建立,但不保證平台恰好傳送一次。

更新與操作請傳入最新詳細回應中的 expected_version。如有衝突,請重新取得貼文,並依新版本檢閱變更。回應遺失時應檢查既有狀態,不應使用新鍵另建貼文。

重複內容防護可能會拒絕獨立請求,如果其標準化公開內容、帳號和臨近發布時間相同。如獲准讀取,請檢查現有貼文參照,並在更改請求前詢問使用者。批次請求會為每個目標回傳結果;部分可能成功,其他則失敗。

7. 錯誤、速率限制與整合限制

處理常式錯誤使用包含 error、message、選填 code、retryable、request_id、選填 details 和 retry_after_seconds 的封裝。schema 驗證 400 錯誤回傳不同結構:{ success: false, error: { name: "ZodError", message: "…" } }。驗證訊息目前包含序列化欄位問題及其路徑;不要假定處理常式封裝欄位存在。

診斷失敗時,請保留 HTTP 狀態、錯誤碼,以及 result.request_id ?? response.headers.get("x-request-id") 的關聯 ID。使用驗證欄位路徑修正請求。若為驗證或權限錯誤,請先修正憑證或授權再重試。

studio-api 目前限制為每位人工使用者每分鐘 240 個請求,以及該使用者獨立機器憑證配額桶每分鐘 480 個請求。這是請求上限,不是發布吞吐量或方案配額。其他端點和社群平台有各自限制。收到 429 或可重試 503 時,遵循即時 Retry-After 回應頭;不要忙循環。

使用者跟進貼文期間,以有界限的間隔讀取狀態,或使用應用程式即時狀態視圖。此 API 不承諾向外傳送 webhooks、訂閱者 SLA、各平台功能一致或固定發布時間。

HTTP 回應與有用的後續操作
狀態含義與回應
400schema 驗證可能回傳 success:false,並在 error 中包含 ZodError,而非處理常式封裝。修正其欄位問題;如內容無 request_id,使用 x-request-id。處理常式層面的無效或不支援請求也可能回傳 400。
401 / 403憑證缺少/過期,或能力、角色、Workspace 或帳號存取遭拒。請修正確切的授權或成員資格。
404此資源在已授權範圍內不可用。請驗證身分。
409狀態/版本、冪等性、重複內容或資格衝突。請重新讀取,不要盲目重送。
批次建立時為 422沒有目標成功。檢查 failures;部分成功則使用 201。
429請求節流。遵循 Retry-After,並保持相同的意圖識別。
503 / 其他 5xx暫時服務失敗或內部錯誤。保留 request_id;重試結果不明的變更前,先檢查既有狀態。