게시물
모든 Posts 엔드포인트와 각 엔드포인트의 cURL, Python 및 Node 예제: 공지, 이벤트 및 혜택, 예약, 사업장별 캠페인과 일괄 캠페인, 상태 폴링 및 삭제.
게시물은 사업장의 Google Business Profile 또는 Facebook 페이지에 게시하는 짧은 소식으로, 공지, 날짜가 지정된 이벤트 또는 쿠폰이 포함된 혜택입니다. 하나의 캠페인으로 여러 사업장과 두 사이트를 동시에 대상으로 지정할 수 있습니다. 게시는 비동기 방식으로 처리되므로 모든 생성 호출은 즉시 반환되며, 결과를 확인하려면 폴링합니다. GET 엔드포인트 3개는 Read(읽기) 키로 사용할 수 있으며, 생성 및 삭제에는 Write(쓰기) 키가 필요합니다.
엔드포인트 한눈에 보기
모든 곳에서 사용하는 값
아래의 열거형 4개는 모든 생성 엔드포인트에서 공통으로 사용합니다.
공지 게시
POST /posts
공지에는 메시지가 필요하며, 사이트마다 버튼 1개와 이미지 1개를 선택적으로 포함할 수 있습니다. postSites에 나열된 사이트마다 postMessage 항목을 1개씩 제공합니다. 게시는 백그라운드에서 실행되므로 응답은 status가 INPROGRESS로 설정된 새 캠페인을 반환합니다.
매개변수
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" } ] }}'{ "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이 누락되면 전송 전에 유효성 검사 오류를 발생시킵니다.
매개변수
공지 표의 모든 항목도 적용됩니다.
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." } ] }}'{ "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는 게시물이 아닌 혜택의 유효 기간을 정합니다.
매개변수
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" } ] }}'{ "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 항목, 참여 집계 수치가 포함되며, 게시에 성공하면 실제 게시물 링크도 포함됩니다.
매개변수
curl https://listingsapi.com/api/v4/posts/U29jaWFsUG9zdDo0NDEyMg== \-H "Authorization: API $LISTINGSAPI_KEY"{ "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개이며, 각각 서로 다른 질문에 답합니다.
캠페인이 SUCCESS로 표시되더라도 그 안의 한 사이트는 ERROR 상태일 수 있으므로, 항상 최상위 상태만 보지 말고 publishDetails도 확인합니다.
사업장의 게시물 목록 조회
GET /locations/{locationId}/posts
특정 사업장을 포함하는 모든 캠페인의 이력을 오프셋 기반 페이지네이션으로 제공하며, data.postsByLocation 아래에 반환합니다. 새 게시물을 예약하기 전에 이를 사용하여 이미 게시된 내용을 점검합니다.
매개변수
curl "https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/posts?page=1&perPage=10" \-H "Authorization: API $LISTINGSAPI_KEY"{ "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}
삭제는 영구적이며, 게시물이 게시된 모든 사이트에서 게시를 취소합니다. 실행 취소 기능이나 수정 엔드포인트가 없으므로, 게시 중인 게시물을 바로잡으려면 삭제한 후 대체 게시물을 게시해야 합니다.
매개변수
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" }'{ "data": { "deleteSocialPost": { "success": true, "socialPostId": "U29jaWFsUG9zdDo0NDEyMg==" } }}존재하지 않거나 이미 삭제된 게시물을 삭제하면 success: false 대신 data가 null인 오류 응답이 반환됩니다.
여러 사업장에 캠페인 1개 게시
POST /bulk-posts
POST /posts와 동일한 규약을 사용하며, 다수의 사업장을 위해 설계되었습니다. locationIds에 모든 사업장을 나열하면 캠페인 1개로 모두 처리합니다. 응답은 POST /posts와 마찬가지로 createSocialPost 키 아래에 반환됩니다.
매개변수
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" } }}'{ "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에는 매장별 분석 내역이 포함됩니다.
매개변수
curl https://listingsapi.com/api/v4/bulk-posts/U29jaWFsUG9zdDo1MTA4OA== \-H "Authorization: API $LISTINGSAPI_KEY"{ "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 아래에서 오프셋 기반 페이지네이션을 사용합니다. 사업장별 목록과 달리 이 엔드포인트는 필터와 정렬을 지원하므로 캠페인 대시보드에 적합한 엔드포인트입니다.
매개변수
정렬 가능한 필드는 name, type, status, created_at, schedule_start_date, schedule_end_date, client_name, clicks, views, shares입니다.
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"}'{ "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 인코딩하므로, 해당 언어의 기본 딕셔너리나 객체로 전달합니다.
발생할 수 있는 오류
전체 목록은 오류 코드에 있습니다.
다음 단계
- 게시물 게시: 이 페이지의 작업 중심 버전으로, 예약 캠페인을 처음부터 끝까지 안내합니다.
- 등록 정보 상태 및 라이브 링크 확인: 사업장에 게시물을 게시하기 전에 해당 사업장이 Google에 공개되어 있는지 확인합니다.
- Google 연결 및 사업장 가져오기: 어떤 사이트에서든 게시물을 수락하려면 먼저 사업장에 연결된 계정이 있어야 합니다.
- 웹훅으로 이벤트에 대응:
local_post이벤트는 게시 결과를 확인하기 위한 폴링을 대체합니다. - 위의 모든 엔드포인트에 대한 전체 필드 목록은 게시물 참조 문서를 참조합니다.