參考資料
Webhook
當貼文送出審核、獲得核准、發布或失敗、檔案準備就緒,或社群帳號需要處理時,你的伺服器會收到一個已簽署的請求。
新增端點
- 1
在 SPREVA 中開啟開發人員,再開啟 Webhook,新增你伺服器的位址,並選擇它要接收的事件。位址必須是公開的,並在 10 秒內以 2xx 狀態碼回應。
- 2
複製端點密鑰。它只會顯示一次,你要用它驗證每個請求的簽章。
- 3
使用傳送測試。它會傳送一個
webhook.test事件,簽署方式和真正的事件相同,最近的傳送會顯示你的伺服器回應的狀態碼和耗時。
你也可以透過 REST API,用具備 webhooks:write 的金鑰新增端點。
每個請求包含的內容
一個 POST 請求,包含 JSON 本文和四個標頭:
x-spreva-event:事件,例如target.published。x-spreva-event-id:和本文的id相同,每次重試和重新傳送時也相同。x-spreva-timestamp:請求簽署的時間,以 Unix 秒數表示。x-spreva-signature:v1=後面接著簽章。
{
"id": "7f3c2d10-0000-4000-8000-000000000000",
"type": "target.published",
"createdAt": "2026-10-01T09:00:02.412Z",
"workspaceId": "0b9f6c1e-0000-4000-8000-000000000001",
"data": {
"type": "TargetPublished",
"workspaceId": "0b9f6c1e-0000-4000-8000-000000000001",
"postId": "5d2a7c3e-0000-4000-8000-000000000002",
"targetId": "9a1f4b7d-0000-4000-8000-000000000003",
"provider": "instagram",
"remoteId": "17900000000000000",
"remoteUrl": "https://www.instagram.com/p/EXAMPLE/"
}
}data 是事件本身,data.type 是它在 SPREVA 中的名稱。用 data 中的 ID,透過 REST API 取得完整的物件。
事件
端點會收到它選擇的事件。無論選擇了什麼,傳送測試都會傳到端點。
貼文
post.created- 已建立貼文
post.review_requested- 貼文已送出審核
post.approved- 貼文已核准並設定時間
post.changes_requested- 審核者附上備註退回貼文
post.scheduled- 貼文已設定日期
post.published- 貼文已發布到所有帳號
post.partial- 貼文在各帳號的結果不一
post.failed- 貼文在所有帳號都發布失敗
發布(每個帳號一次)
target.published- 一個帳號已發布貼文
target.failed- 一個帳號無法發布
target.awaiting_user- 某個帳號需要你在它自己的應用程式中完成發布
媒體
media.ready- 上傳的檔案已可使用
media.failed- 檔案無法處理或生成
社群帳號
connection.expired- 社群帳號需要重新連結
connection.revoked- 社群帳號撤回了權限
數據分析
analytics.updated- 已發布的貼文有新的數據
驗證簽章
簽章是以端點密鑰為金鑰,對時間戳記、一個句點和原始本文計算的 HMAC-SHA256。簽章不符的請求一律拒絕。
import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody: the request body as a string, before any JSON parsing
export function isFromSpreva(rawBody, headers, secret) {
const signed = headers["x-spreva-timestamp"] + "." + rawBody;
const expected = Buffer.from("v1=" + createHmac("sha256", secret).update(signed).digest("hex"));
const received = Buffer.from(headers["x-spreva-signature"] ?? "");
return received.length === expected.length && timingSafeEqual(received, expected);
}在進行任何 JSON 剖析之前,用收到的原始本文驗證:剖析後再寫回會改變位元組,簽章就不再相符。
重試和重新傳送
- 在 10 秒內以 2xx 狀態碼回應。任何其他回應或沒有回應,都會重試最多 5 次:分別在 30 秒、2 分鐘、10 分鐘、1 小時和 6 小時後。
- 不會追蹤重新導向,所以請使用端點的最終位址。
- 重試或重新傳送會帶有相同的
x-spreva-event-id:用它忽略已經處理過的事件。 - 「最近的傳送」中的重新傳送會再次傳送事件,如果你的伺服器仍然失敗也會重試,讓你可以修正端點,而不必重複發布。