POST
/api/v4/social/bulk-posts大量建立貼文
在單一請求中驗證最多 500 則社群貼文並將其排入佇列,傳回可供輪詢的工作,以取得各資料列的結果。
參數
請求主體
標示為必填的巢狀欄位僅在您傳送其上層欄位時適用。如果上層欄位為選填且您省略它,其必填子欄位便不適用。
| 名稱 | 類型 | 必填 | 說明 |
|---|---|---|---|
| input | object | 必填 | Wrapper object. The entire request body must be nested under `input`. |
| input.posts | array of objects | 必填 | The rows to create, 1 to 500 of them. Each row is the same object POST /social/posts takes as its `input`; the per-row fields are listed below. |
| input.name | string | 選填 | Optional label for the job itself, to identify it in your own logs. Not shown to any audience. |
| input.posts[].socialProfileId | string | 必填 | UUID of the brand publishing this row. Rows may target different brands in one request. |
| input.posts[].name | string | 必填 | Internal name for the post. |
| input.posts[].platforms | array of strings | 必填 | Platforms for this row: `FACEBOOK`, `INSTAGRAM`, `TWITTER` (X), `LINKEDIN`, `PINTEREST`. Each must already have a connection on that row's brand. |
| input.posts[].content | string | 必填 | The post body. |
| input.posts[].action | string | 必填 | `DRAFT`, `SCHEDULE` (requires a schedule) or `PUBLISH`. |
| input.posts[].mediaUrls | array of strings | 選填 | Public https image URLs. Required when the row targets Instagram or Pinterest. |
| input.posts[].videoUrls | array of strings | 選填 | Public https video URLs. |
| input.posts[].link | string | 選填 | Link to attach where the platform supports one. |
| input.posts[].scheduledAt | string | 選填 | ISO-8601 publish instant with an offset. Alternative to `scheduleDate` + `scheduleTime`, never both. |
| input.posts[].scheduleDate | string | 選填 | `YYYY-MM-DD`, interpreted in that row's brand timezone. Send with `scheduleTime`. |
| input.posts[].scheduleTime | string | 選填 | `HH:MM`, interpreted in that row's brand timezone. Send with `scheduleDate`. |
| input.posts[].connectedChannelIds | array of strings | 選填 | Restrict this row to specific connections by ID. |
| input.posts[].clientReference | string | 選填 | Your own identifier for this row, echoed back on the matching job result. The most reliable way to reconcile a batch against your own records. |
請求範例
可直接貼上的請求主體。請將預留位置 ID 與值換成您自己的。
{ "input": { "name": "Autumn campaign load", "posts": [ { "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", "name": "Autumn week 1", "platforms": ["INSTAGRAM", "FACEBOOK"], "content": "Week one of the autumn collection: the Fairfield oak sideboard, finished by hand in the workshop.", "mediaUrls": ["https://cdn.example.com/social/autumn-w1.jpg"], "action": "SCHEDULE", "scheduleDate": "2026-10-02", "scheduleTime": "09:30", "clientReference": "campaign-4471-slot-01" }, { "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", "name": "Autumn week 2", "platforms": ["INSTAGRAM", "FACEBOOK", "LINKEDIN"], "content": "Week two: the Halcyon armchair. Sixty hours of work, one chair.", "mediaUrls": ["https://cdn.example.com/social/autumn-w2.jpg"], "action": "SCHEDULE", "scheduleDate": "2026-10-09", "scheduleTime": "09:30", "clientReference": "campaign-4471-slot-02" }, { "socialProfileId": "a90f7c22-5db1-4e83-9f40-2b7c6a1e5d33", "name": "Eastside autumn teaser", "platforms": ["INSTAGRAM"], "content": "Something solid is arriving next week. Stay tuned.", "mediaUrls": ["https://cdn.example.com/social/eastside-teaser.jpg"], "action": "SCHEDULE", "scheduledAt": "2026-10-01T08:00:00-04:00", "clientReference": "campaign-4471-slot-03" } ] }}回應
200The whole batch validated. A job was queued, poll GET /social/bulk-posts/{bulkJobId} for per-row results.
{ "data": { "createBulkSocialMediaPosts": { "success": true, "error": [], "job": { "id": "9b3f18d0-7a26-4c51-8e94-1f0d5c6b7a82", "status": "QUEUED", "totalCount": 3, "processedCount": 0, "successCount": 0, "failureCount": 0, "createdAt": "2026-09-28T14:04:52Z", "updatedAt": "2026-09-28T14:04:52Z", "results": [] } } }}200At least one row failed validation, so **nothing was created**. `success` is `false`, no job is returned, and each rejected row is reported with its 0-based `index`.
{ "data": { "createBulkSocialMediaPosts": { "success": false, "error": [ { "message": "SY95050: Bulk validation failed, no posts were created", "code": "SY95050", "contextInfo": null } ], "job": { "id": null, "status": "FAILED", "totalCount": 3, "processedCount": 0, "successCount": 0, "failureCount": 2, "createdAt": "2026-09-28T14:04:52Z", "updatedAt": "2026-09-28T14:04:52Z", "results": [ { "index": 1, "clientReference": "campaign-4471-slot-02", "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", "platforms": ["INSTAGRAM", "FACEBOOK", "LINKEDIN"], "status": "INVALID", "socialPostId": null, "postStatus": null, "errors": [ { "message": "SY95045: No connected channel for LINKEDIN on this brand", "code": "SY95045", "contextInfo": [{ "key": "platform", "value": "LINKEDIN" }] } ] }, { "index": 2, "clientReference": "campaign-4471-slot-03", "socialProfileId": "a90f7c22-5db1-4e83-9f40-2b7c6a1e5d33", "platforms": ["INSTAGRAM"], "status": "INVALID", "socialPostId": null, "postStatus": null, "errors": [ { "message": "SY95046: scheduledAt must carry a UTC offset", "code": "SY95046", "contextInfo": null } ] } ] } } }}401Unauthenticated, missing or invalid API key.
在單一請求中建立多則社群貼文。資料列會包含在請求承載資料中傳送,不需要上傳檔案,也不使用 CSV,只需提供一個陣列,其中的物件與 POST /social/posts 每次接受的單一物件相同。每個請求最多可包含 500 個資料列。
使用案例:透過一次呼叫載入一季的內容。您的規劃工具中已有客戶完整的內容行事曆。為每個時段建立一個資料列,以您自己的 clientReference 標記各資料列,再一併傳送。整批資料會全部成功,或明確告知您需要修正哪些資料列。儲存傳回的 job.id,並輪詢 GET /social/bulk-posts/{bulkJobId},直到 status 處於終止狀態,再依各結果的 clientReference 核對。
預先驗證整批資料
在建立任何內容之前,會先驗證所有資料列,在這個階段,整批資料視為一個整體:
- 只要有任何一個資料列無效,就不會建立任何內容。
success為false,SY95050會在error中傳回,而每個有問題的資料列都會列於job.results[]中,包含其從 0 起算的index、其clientReference,以及errors[]中的原因。請修正這些資料列,然後重新傳送整批資料。 - 如果所有資料列都有效,系統會將工作排入佇列,
success為true,且您會取得job.id。個別資料列仍可能在稍後發布時遭平台拒絕而失敗;這類失敗會顯示在工作中,不會顯示在此處。
請盡可能依 clientReference 核對,否則就依 index 核對;系統不會原樣傳回資料列,因此這 2 個欄位是結果與您自身資料之間唯一的關聯。
注意事項。
- 請求主體必須包在
input物件中,並將資料列放在input.posts中。 - 請檢查
success,而非 HTTP 狀態。整批遭拒絕時,結果為HTTP 200,並帶有success: false以及error中的SY95050。 - 每個請求最多 500 個資料列。超過此上限的陣列會直接遭到拒絕,並傳回
SY95048,且不會建立任何內容;請將其拆分為多個批次傳送。 - 每個資料列的品牌欄位為
socialProfileId。brandId一律僅用作 URL 路徑中的佔位符,而此路由完全沒有路徑佔位符。 - 資料列可以指定不同的品牌。系統會根據每個資料列所屬的品牌檢查該資料列的
platforms,因此,若某平台已連結至一個品牌,但未連結至另一個品牌,就只有需要該平台的資料列會失敗。 - 每個資料列都遵循與單則貼文相同的排程規則:使用
scheduledAt或scheduleDate+scheduleTime,兩者不可同時使用,且scheduleDate/scheduleTime會依該資料列所屬品牌的時區解讀。同一批次中的不同資料列可以混用這 2 種形式。 - 速率限制適用於請求,而非資料列:包含 500 個資料列的批次只會占用您配額中的 1 次請求。請參閱速率限制。
寫入操作:未對正式帳戶執行。此處顯示的請求與回應是根據 API 結構描述建構的;執行此操作時,會將內容發布至真實的社群帳號。
Request
curl -X POST 'https://listingsapi.com/api/v4/social/bulk-posts' \ -H "Authorization: API $LISTINGSAPI_KEY" \ -H 'Content-Type: application/json' \ -d '{ "input": { "name": "Autumn campaign load", "posts": [ { "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", "name": "Autumn week 1", "platforms": [ "INSTAGRAM", "FACEBOOK" ], "content": "Week one of the autumn collection: the Fairfield oak sideboard, finished by hand in the workshop.", "mediaUrls": [ "https://cdn.example.com/social/autumn-w1.jpg" ], "action": "SCHEDULE", "scheduleDate": "2026-10-02", "scheduleTime": "09:30", "clientReference": "campaign-4471-slot-01" }, { "socialProfileId": "6f2c9a41-7b0e-4d55-9a2f-3c8e1d47b902", "name": "Autumn week 2", "platforms": [ "INSTAGRAM", "FACEBOOK", "LINKEDIN" ], "content": "Week two: the Halcyon armchair. Sixty hours of work, one chair.", "mediaUrls": [ "https://cdn.example.com/social/autumn-w2.jpg" ], "action": "SCHEDULE", "scheduleDate": "2026-10-09", "scheduleTime": "09:30", "clientReference": "campaign-4471-slot-02" }, { "socialProfileId": "a90f7c22-5db1-4e83-9f40-2b7c6a1e5d33", "name": "Eastside autumn teaser", "platforms": [ "INSTAGRAM" ], "content": "Something solid is arriving next week. Stay tuned.", "mediaUrls": [ "https://cdn.example.com/social/eastside-teaser.jpg" ], "action": "SCHEDULE", "scheduledAt": "2026-10-01T08:00:00-04:00", "clientReference": "campaign-4471-slot-03" } ] } }'