貼文

每個貼文端點皆附有 cURL、Python 和 Node 範例:涵蓋公告、活動與優惠、排程、個別地點與大量行銷活動、狀態輪詢及刪除。

貼文是發布至地點的 Google Business Profile 或 Facebook 粉絲專頁的簡短動態:可以是公告、附有日期的活動,或包含優惠券的優惠。單一行銷活動可以同時指定多個地點及這兩個網站。發布作業採非同步方式進行,因此每次建立呼叫都會立即傳回,您需透過輪詢取得結果。這三個 GET 端點可使用 Read(讀取)金鑰;建立與刪除則需要 Write(寫入)金鑰。

端點一覽

方法路徑功能參考文件
POST/posts發布公告,即純文字訊息,可選擇附加按鈕與圖片。建立公告貼文
POST/posts發布活動,包含標題及開始與結束時間。建立活動貼文
POST/posts發布優惠,包含優惠券代碼、折扣與條款。建立優惠貼文
GET/posts/{postId}單一行銷活動,包含各網站的發布狀態與互動次數。取得貼文
GET/locations/{locationId}/posts以某個地點為目標的行銷活動,傳回一頁結果。擷取地點的貼文
DELETE/posts/{postId}永久刪除行銷活動,並在所有發布處取消發布。刪除貼文
POST/bulk-posts將單一行銷活動發布至多個地點。建立大量貼文
GET/bulk-posts/{postId}單一大量行銷活動,包含按地點細分的分析資料。依 ID 擷取大量貼文
GET/locations/{locationId}/bulk-posts包含某個地點的大量行銷活動,支援篩選與排序。擷取地點的大量貼文

各處都會用到的值

以下四個列舉皆由所有建立端點共用。

欄位接受的值
postTypeANNOUNCEMENT, EVENT, OFFER, COVID19, PRODUCT
postSites 與每個 siteGOOGLE, FACEBOOK
postCta[].typeBOOK, ORDER, SHOP, LEARN_MORE, SIGN_UP, GET_OFFER
postMediaUrl[].typeIMAGE, VIDEO

發布公告

POST /posts

公告接受一則訊息,並可為每個網站選擇附加一個按鈕與一張圖片。請為 postSites 中列出的每個網站提供一筆 postMessage 項目。回應會傳回新建立的行銷活動,其 status 設為 INPROGRESS,因為發布作業會在背景執行。

參數

名稱所在位置必填備註
input.postNamebody是內部行銷活動名稱,絕不會向客戶顯示。
input.locationIdsbody是base64 地點 id 的陣列。
input.postTypebody是此處使用 ANNOUNCEMENT。
input.postSitesbody是包含 GOOGLE 與 FACEBOOK 的陣列。
input.postMessagebody否物件陣列,每個物件包含 site 與 message。
input.postCtabody否物件陣列,每個物件包含 site、type、url。
input.postMediaUrlbody否物件陣列,每個物件包含 site、url、type。
input.clientMutationIdbody否原樣傳回,以供關聯比對。
Announcement
curl -X POST https://listingsapi.com/api/v4/posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "postName": "Grand Opening Announcement",    "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="],    "postType": "ANNOUNCEMENT",    "postSites": ["GOOGLE"],    "postMessage": [      { "site": "GOOGLE", "message": "We are now open! Visit us this week for our grand opening." }    ],    "postCta": [      { "site": "GOOGLE", "type": "LEARN_MORE", "url": "https://jennyhome.example/opening" }    ],    "postMediaUrl": [      { "site": "GOOGLE", "url": "https://cdn.example.com/opening.jpg", "type": "IMAGE" }    ]  }}'
JSON
{  "data": {    "createSocialPost": {      "success": true,      "errors": [],      "socialPost": {        "id": "U29jaWFsUG9zdDo0NDEyMg==",        "name": "Grand Opening Announcement",        "status": "INPROGRESS",        "type": "ANNOUNCEMENT",        "sites": ["GOOGLE"],        "publishDetails": [          { "site": "GOOGLE", "status": "PUBLISHING", "createdDate": "2026-06-28", "submissionError": null }        ],        "postLinks": [],        "locationIds": [1800289]      }    }  }}

請保留 socialPost.id。這是此處其他所有端點都需要的 base64 貼文 id。兩個 SDK 的輔助函式都接受單一 message 字串,並將其展開為每個網站各一筆項目,因此您只需在 cURL 中手動建立 postMessage 陣列。

發布活動

POST /posts

活動會顯示為附有日期的卡片。活動本身的時程位於 postContextInfo。獨立的 postScheduledDates 物件控制貼文本身何時顯示及到期,這段期間通常是活動開始前的宣傳期。Google 會拒絕沒有標題的活動,而兩個 SDK 都會在缺少 title 時,於傳送前拋出驗證錯誤。

參數

名稱所在位置必填備註
input.postTypebody是此處使用 EVENT。
input.postContextInfo.titlebody實務上必填活動標題。Google 會拒絕沒有標題的活動。
input.postContextInfo.startDay, endDaybody否日期,YYYY-MM-DD。
input.postContextInfo.startTime, endTimebody否顯示用字串,例如 10:00am。
input.postScheduledDatesbody否包含 startDatetime、endDatetime、removalSites 的物件。

公告表格中的所有項目也都適用。

Event
curl -X POST https://listingsapi.com/api/v4/posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "postName": "Summer Sale Kickoff Event",    "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="],    "postType": "EVENT",    "postSites": ["GOOGLE"],    "postContextInfo": {      "title": "Summer Sale Kickoff",      "startDay": "2026-07-15",      "startTime": "10:00am",      "endDay": "2026-07-15",      "endTime": "06:00pm"    },    "postMessage": [      { "site": "GOOGLE", "message": "Join us for the Summer Sale kickoff, refreshments and up to 40 percent off in store." }    ]  }}'
JSON
{  "data": {    "createSocialPost": {      "success": true,      "socialPost": {        "id": "U29jaWFsUG9zdDo0NDEyMw==",        "status": "INPROGRESS",        "type": "EVENT",        "scheduledStartDate": "2026-07-15",        "scheduledEndDate": "2026-07-15",        "contextInfo": {          "title": "Summer Sale Kickoff",          "startDay": "2026-07-15",          "startTime": "10:00am",          "endDay": "2026-07-15",          "endTime": "06:00pm"        }      }    }  }}

傳回的 contextInfo 是活動期間。scheduledStartDate 與 scheduledEndDate 描述貼文本身的時程;此處因為未傳送 postScheduledDates,所以貼文時程與活動日期相同。

發布優惠

POST /posts

優惠是一張促銷卡片,包含優惠碼、折扣、兌換連結和條款。這些內容全都放在 postContextInfo 中,而 startDay 與 endDay 界定的是優惠的有效期間,而非貼文的有效期間。

參數

名稱所在位置必填備註
input.postTypebody是此處為 OFFER。
input.postContextInfo.titlebody實務上必填用於標示優惠。兩個 SDK 都要求提供此欄位。
input.postContextInfo.couponCodebody否顧客兌換時使用的代碼。
input.postContextInfo.discountbody否自由文字,例如 25%。
input.postContextInfo.redeemUrlbody否兌換優惠的網址。
input.postContextInfo.termsConditionsbody否詳細條款。
input.postContextInfo.startDay, endDaybody否有效期間,YYYY-MM-DD。
Offer
curl -X POST https://listingsapi.com/api/v4/posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "postName": "Festive 25 Percent Off",    "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="],    "postType": "OFFER",    "postSites": ["GOOGLE"],    "postContextInfo": {      "title": "25% off storewide",      "couponCode": "FESTIVE25",      "discount": "25%",      "redeemUrl": "https://jennyhome.example/festive",      "termsConditions": "Valid in-store only through July 6.",      "startDay": "2026-06-22",      "endDay": "2026-07-06"    },    "postMessage": [      { "site": "GOOGLE", "message": "Celebrate with us, 25 percent off everything in store this week." }    ],    "postCta": [      { "site": "GOOGLE", "type": "GET_OFFER", "url": "https://jennyhome.example/festive" }    ]  }}'
JSON
{  "data": {    "createSocialPost": {      "success": true,      "socialPost": {        "id": "U29jaWFsUG9zdDo0NDEyNA==",        "status": "INPROGRESS",        "type": "OFFER",        "contextInfo": {          "title": "25% off storewide",          "couponCode": "FESTIVE25",          "discount": "25%",          "startDay": "2026-06-22",          "endDay": "2026-07-06"        }      }    }  }}

Google 的優惠按鈕使用 ORDER,Facebook 則使用 GET_OFFER。如果促銷提前結束,請刪除行銷活動,而非編輯活動。

讀取單篇貼文及其狀態

GET /posts/{postId}

傳回已接受之行銷活動的發布結果。回應中的 data.socialPostView 包含行銷活動內容、每個網站各一筆的 publishDetails 項目、互動計數,以及發布成功後的上線連結。

參數

名稱所在位置必填備註
postIdpath是來自建立回應或清單的 Base64 貼文 id。
Get a post
curl https://listingsapi.com/api/v4/posts/U29jaWFsUG9zdDo0NDEyMg== \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "socialPostView": {      "socialPostId": "U29jaWFsUG9zdDo0NDEyMg==",      "socialPostInfo": {        "status": "SUCCESS",        "type": "ANNOUNCEMENT",        "views": 128,        "clicks": 14,        "publishDetails": [          { "site": "GOOGLE", "status": "PUBLISHED", "publishedDate": "2026-06-28", "submissionError": null }        ],        "postLinks": [          { "site": "GOOGLE", "link": "https://www.google.com/maps/place/?post=44122" }        ]      },      "publishedLocationsCount": 1,      "socialPostAnalyticsBySite": [        { "site": "GOOGLE", "views": 128, "clicks": 14, "reactions": 3, "shares": 0, "comments": 1 }      ]    }  }}

有兩個重要的狀態欄位,分別回答不同的問題。

欄位值意義
socialPostInfo.statusINPROGRESS已接受,仍在發布中。
SUCCESS發布已完成。請讀取 publishDetails,查看各網站的結果。
SCHEDULED正在等待 postScheduledDates 時段開始。
EXPIRED排定的時段已結束,貼文已下線。
publishDetails[].statusPUBLISHING該網站尚未回應。
PUBLISHED已在該網站上線。請在 postLinks 中查看 URL。
ERROR該網站已拒絕發布。submissionError 說明了原因。

行銷活動可能顯示為 SUCCESS,但其中某個網站的狀態卻是 ERROR,因此務必檢查 publishDetails,不要只查看頂層狀態。

列出地點的貼文

GET /locations/{locationId}/posts

在 data.postsByLocation 下提供所有包含指定地點之行銷活動的歷史紀錄,並使用位移量分頁。在排程新內容之前,可用它來查核已上線的內容。

參數

名稱所在位置必填備註
locationIdpath是Base64 id,原樣傳入。
pagequery否從 1 開始的頁碼,預設為 1。
perPagequery否預設為 10,不得超過 50。
Posts on a location
curl "https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/posts?page=1&perPage=10" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "postsByLocation": {      "records": [        {          "id": "U29jaWFsUG9zdDo0NDEyMg==",          "name": "Summer Hours Update",          "status": "SUCCESS",          "type": "ANNOUNCEMENT",          "createdAt": "2026-06-28",          "views": 128,          "clicks": 14,          "sites": ["GOOGLE"]        }      ],      "pageInfo": { "totalPages": 1, "hasNextPage": false, "totalRecords": 1 }    }  }}

此路由不提供伺服器端篩選。它只接受 page 和 perPage,其餘參數都會被忽略,因此請讀取每筆紀錄的 type 和 status,並在您自己的程式碼中篩選。如需在伺服器端排序及篩選,請改用下方的大量貼文清單端點。

刪除貼文

DELETE /posts/{postId}

此操作會永久刪除貼文,並從所有已發布該貼文的網站將其下架。此操作無法復原,也沒有編輯端點,因此若要修正已上線的貼文,必須先刪除它,再發布替代貼文。

參數

名稱所在位置必填備註
postIdpath是Base64 貼文 id。
clientMutationIdbody否選填,會原樣傳回以供關聯比對。
Delete
curl -X DELETE https://listingsapi.com/api/v4/posts/U29jaWFsUG9zdDo0NDEyMg== \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "clientMutationId": "delete-44122-req-1" }'
JSON
{  "data": {    "deleteSocialPost": {      "success": true,      "socialPostId": "U29jaWFsUG9zdDo0NDEyMg=="    }  }}

刪除不存在或已刪除的貼文時,會傳回錯誤回應,其中 data 設為 null,而非 success: false。

將單一行銷活動發布至多個地點

POST /bulk-posts

此端點與 POST /posts 採用相同的介面規格,專為管理大量地點而設計:在 locationIds 中列出所有地點,單一行銷活動便能涵蓋全部地點。回應以 createSocialPost 為鍵,與 POST /posts 相同。

參數

名稱所在位置必填備註
input.postNamebody是內部使用的行銷活動名稱。
input.locationIdsbody是所有要發布至的地點之 base64 id。
input.postTypebody是EVENT、OFFER 和 PRODUCT 也需要 postContextInfo 或 products。
input.postSitesbody是GOOGLE、FACEBOOK,或兩者皆有。
input.postScheduledDatesbody否以 ISO 8601 格式提供 startDatetime 和 endDatetime。建立的貼文狀態為 SCHEDULED。
input.componentIdentifierbody否您自訂的參照值,方便日後用於篩選。
Bulk publish
curl -X POST https://listingsapi.com/api/v4/bulk-posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "postName": "July Reopening Announcement",    "locationIds": ["TG9jYXRpb246MTgwMDI4OQ==", "TG9jYXRpb246MTgwMDI5MA=="],    "postType": "ANNOUNCEMENT",    "postSites": ["GOOGLE", "FACEBOOK"],    "postMessage": [      { "site": "GOOGLE", "message": "We are back. Visit us this week for our summer menu." },      { "site": "FACEBOOK", "message": "We are back. Swing by for the new summer menu." }    ],    "postScheduledDates": {      "startDatetime": "2026-07-10T09:00:00Z",      "endDatetime": "2026-07-24T23:59:00Z"    }  }}'
JSON
{  "data": {    "createSocialPost": {      "success": true,      "errors": null,      "socialPost": {        "id": "U29jaWFsUG9zdDo5OTIwMQ==",        "name": "July Reopening Announcement",        "status": "SCHEDULED",        "type": "ANNOUNCEMENT",        "scheduledStartDate": "2026-07-10",        "scheduledEndDate": "2026-07-24",        "sites": ["GOOGLE", "FACEBOOK"],        "locationIds": [1800289, 1800290]      }    }  }}

兩個 SDK 的輔助函式都會將 sites 預設為 Google 和 Facebook、為您展開各網站的訊息對應表,並將數字地點 id 編碼,因此在任一 SDK 中,大量發布通常是最簡短的呼叫。

讀取單一大量行銷活動

GET /bulk-posts/{postId}

這是 GET /posts/{postId} 的大量版本。它傳回相同的結構,其中 publishedLocationsCount 大於 1,並在 socialPostAnalyticsByLocationId 中提供各門市的分析明細。

參數

名稱所在位置必填備註
postIdpath是Base64 編碼的大量貼文 ID,不是原始整數。
Get a bulk post
curl https://listingsapi.com/api/v4/bulk-posts/U29jaWFsUG9zdDo1MTA4OA== \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "socialPostView": {      "socialPostId": "U29jaWFsUG9zdDo1MTA4OA==",      "socialPostInfo": {        "name": "Festive Offer - All Stores",        "status": "SUCCESS",        "type": "OFFER",        "views": 4210,        "clicks": 318,        "sites": ["GOOGLE", "FACEBOOK"]      },      "socialPostAnalyticsByLocationId": [        {          "locationId": 1800289,          "siteStats": [            { "site": "GOOGLE", "status": "PUBLISHED", "views": 1040, "clicks": 80 },            { "site": "FACEBOOK", "status": "PUBLISHED", "views": 360, "clicks": 26 }          ]        }      ]    }  }}

socialPostAnalyticsBySite 彙總行銷活動在所有門市的資料,而 socialPostAnalyticsByLocationId 則按門市列出相同資料的明細。查看各門市的 status 值,找出有網站發布失敗的地點。

列出某個地點的大量行銷活動

GET /locations/{locationId}/bulk-posts

在 data.rollupSocialPosts 下使用位移量分頁。與個別地點的清單不同,此路由支援篩選和排序,因此適合用於行銷活動儀表板。

參數

名稱所在位置必填備註
locationIdpath是Base64 編碼的 ID,請原樣傳入。
page, perPagequery否位移量分頁。
filtersquery否以 JSON 編碼,依 type、status、creationDateRange 或 siteUrls 篩選。
sortFieldsquery否以 JSON 編碼,例如以欄位 created_at 搭配排序方向 Descending。
locationIdsquery否以 JSON 編碼的陣列,包含要額外納入的地點 ID。
componentIdentifierquery否將結果限制為由您的整合建立的行銷活動。

可排序的欄位為 name、type、status、created_at、schedule_start_date、schedule_end_date、client_name、clicks、views 和 shares。

Bulk posts on a location
curl -G https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/bulk-posts \-H "Authorization: API $LISTINGSAPI_KEY" \--data-urlencode 'page=1' \--data-urlencode 'perPage=10' \--data-urlencode 'sortFields={"field":"created_at","order":"Descending"}'
JSON
{  "data": {    "rollupSocialPosts": {      "records": [        {          "id": "U29jaWFsUG9zdDo1MTA4OA==",          "name": "Festive Offer - All Stores",          "status": "SUCCESS",          "type": "OFFER",          "createdAt": "2026-06-20",          "views": 4210,          "clicks": 318        }      ],      "pageInfo": { "totalPages": 1, "hasNextPage": false, "totalRecords": 1 }    }  }}

兩個 SDK 都會為您將 filters 和 sortFields 物件編碼為 JSON,因此請以原生字典或物件傳入。

您會遇到的錯誤

代碼或狀態意義修正方式
400 缺少 $input 變數請求主體未包在 input 中。將所有欄位巢狀放在單一 input 鍵下。
SY90016,HTTP 狀態為 400建立或刪除操作使用了 Read 金鑰。請使用 Write 金鑰。
401金鑰缺失或無效。請傳送 Authorization: API <YOUR_API_KEY>。
429,並附有 Retry-After呼叫次數過多,通常是因為輪詢貼文狀態。請等待所指定的秒數。請參閱 速率限制。
200,並附有 success: false驗證失敗。請閱讀 data.createSocialPost 中的 errors。
per_page must not exceed 50perPage 超過地點清單的上限。請要求 50 筆或更少。
tag is not a supported parameter for this query將 tag 傳送至個別地點的貼文路由。請只傳送 page 和 perPage。

完整清單請參閱 錯誤代碼。

後續步驟