投稿

すべての投稿エンドポイントを、cURL、Python、Nodeのサンプルとともに紹介します。お知らせ、イベント、特典、スケジュール設定、拠点ごとおよび一括のキャンペーン、ステータスのポーリング、削除を扱います。

投稿は、拠点のGoogle Business ProfileまたはFacebookページに公開する短い更新情報で、お知らせ、日付を指定したイベント、クーポン付きの特典があります。1つのキャンペーンで、多数の拠点と両方のサイトを同時に対象にできます。公開は非同期で行われるため、作成呼び出しはすべて即座に戻り、結果はポーリングで確認します。3つのGETエンドポイントはRead(読み取り)キーで利用できますが、作成と削除にはWrite(書き込み)キーが必要です。

エンドポイント一覧

メソッドパス機能リファレンス
POST/postsボタンと画像を任意で追加できるシンプルなメッセージを、お知らせとして公開します。お知らせの投稿を作成する
POST/postsタイトルと開始・終了日時を指定してイベントを公開します。イベントの投稿を作成する
POST/postsクーポンコード、割引、利用条件を指定して特典を公開します。特典の投稿を作成する
GET/posts/{postId}サイトごとの公開ステータスとエンゲージメント数を含む1つのキャンペーンを取得します。投稿を取得する
GET/locations/{locationId}/posts1つの拠点を対象とするキャンペーンを1ページ分取得します。拠点の投稿を取得する
DELETE/posts/{postId}キャンペーンを完全に削除し、すべての公開先で公開を取り消します。投稿を削除する
POST/bulk-posts1つのキャンペーンを多数の拠点に展開します。一括投稿を作成する
GET/bulk-posts/{postId}拠点ごとの分析内訳を含む1つの一括キャンペーンを取得します。IDで一括投稿を取得する
GET/locations/{locationId}/bulk-posts1つの拠点を含む一括キャンペーンを、フィルターと並べ替えを使用して取得します。拠点の一括投稿を取得する

すべてのエンドポイントで使用する値

以下の4つの列挙型は、すべての作成エンドポイントで共通です。

フィールド指定可能な値
postTypeANNOUNCEMENT, EVENT, OFFER, COVID19, PRODUCT
postSitesとすべてのsiteGOOGLE, FACEBOOK
postCta[].typeBOOK, ORDER, SHOP, LEARN_MORE, SIGN_UP, GET_OFFER
postMediaUrl[].typeIMAGE, VIDEO

お知らせを公開する

POST /posts

お知らせにはメッセージを指定し、サイトごとにボタン1つと画像1つを任意で追加できます。postSitesに記載したサイトごとに、postMessageのエントリを1つ指定してください。公開はバックグラウンドで実行されるため、レスポンスでは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ヘルパーは、1つのmessage文字列を受け取り、サイトごとに1つのエントリへ展開するため、postMessage配列を手動で組み立てる必要があるのはcURLの場合だけです。

イベントを公開する

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 を受け付けます。プロモーションが予定より早く終了した場合は、キャンペーンを編集せずに削除してください。

1 件の投稿とそのステータスを取得する

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 }      ]    }  }}

重要なステータスフィールドは 2 つあり、それぞれ異なる情報を示します。

フィールド値意味
socialPostInfo.statusINPROGRESS受け付け済みで、公開処理はまだ実行中です。
SUCCESS公開処理が完了しました。サイトごとの結果は publishDetails を確認してください。
SCHEDULEDpostScheduledDates の期間が始まるのを待っています。
EXPIRED予定された期間が終了し、投稿は公開されていません。
publishDetails[].statusPUBLISHINGそのサイトからはまだ応答がありません。
PUBLISHEDそのサイトで公開されています。URL は postLinks を確認してください。
ERRORそのサイトが拒否しました。理由は submissionError に記載されています。

キャンペーンが SUCCESS と表示されていても、その中の 1 つのサイトが ERROR になっている場合があるため、最上位のステータスだけでなく、必ず publishDetails を確認してください。

拠点の投稿一覧を取得する

GET /locations/{locationId}/posts

1 つの拠点を含むすべてのキャンペーンの履歴を、オフセット方式のページネーションで 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 が success: false ではなく null に設定されたエラーレスポンスが返されます。

多数の拠点に 1 つのキャンペーンを公開する

POST /bulk-posts

POST /posts と同じ仕様で、多数の拠点向けに設計されており、locationIds にすべての拠点を列挙すると、1 つのキャンペーンですべてを対象にできます。レスポンスは、POST /posts と同様に createSocialPost をキーとして格納されます。

パラメーター

名前指定先必須備考
input.postNamebodyはい内部用のキャンペーン名です。
input.locationIdsbodyはい公開先となるすべての拠点の base64 形式の ID です。
input.postTypebodyはいEVENT、OFFER、PRODUCT には、postContextInfo または products も必要です。
input.postSitesbodyはいGOOGLE、FACEBOOK、またはその両方です。
input.postScheduledDatesbodyいいえstartDatetime と endDatetime を ISO 8601 形式で指定します。投稿を 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 でも一括公開は通常、最も短い呼び出しで行えます。

一括キャンペーンを1件取得する

GET /bulk-posts/{postId}

GET /posts/{postId}の一括処理版です。同じ構造を返しますが、publishedLocationsCountは1より大きく、socialPostAnalyticsByLocationIdには店舗ごとの分析データの内訳が含まれます。

パラメーター

名前指定先必須備考
postIdpathはい整数のIDではなく、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いいえtype、status、creationDateRange、またはsiteUrlsによるフィルターをJSON形式でエンコードします。
sortFieldsqueryいいえたとえば、フィールドをcreated_at、順序をDescendingとして、JSON形式でエンコードします。
locationIdsqueryいいえ追加で含める拠点IDの配列をJSON形式でエンコードします。
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キーの配下にネストしてください。
HTTP 400として返されるSY90016作成または削除にReadキーが使用されました。Writeキーを使用してください。
401キーが指定されていないか、無効です。Authorization: API <YOUR_API_KEY>を送信してください。
429(Retry-After付き)呼び出し回数が多すぎます。多くの場合、投稿ステータスのポーリングが原因です。通知された秒数だけ待ってください。レート制限を参照してください。
200(success: false)検証に失敗しました。data.createSocialPost内のerrorsを確認してください。
per_page must not exceed 50拠点の一覧でperPageが上限を超えています。50以下を指定してリクエストしてください。
tag is not a supported parameter for this query拠点ごとの投稿ルートにtagが送信されました。pageとperPageのみを送信してください。

完全な一覧はエラーコードにあります。

次の手順