/api/v4/locations/{locationId}/postsFetch posts for a location
Returns a page of social post campaigns (announcements, events, offers) that target a single location.
Parameters
Path
| Name | Type | Required | Description |
|---|---|---|---|
| locationId | string | required | Base64-encoded location cursor / global ID (e.g. `TG9jYXRpb246MTgwMDI4OQ==`). Pass it verbatim, do not URL-encode it. The base64 cursor always resolves; the raw numeric database ID also works on this endpoint, but the base64 form is the portable choice across the API. |
Query
| Name | Type | Required | Description | Default |
|---|---|---|---|---|
| page | integer | optional | 1-based page number for offset pagination. | 1 |
| perPage | integer | optional | Number of records per page. | — |
| filters | string | optional | JSON-encoded SocialPostFiltersInput (e.g. by `type`, `status`, `creationDateRange`, `siteUrls`). | — |
| sortFields | string | optional | JSON-encoded sort object `{ "field": "created_at", "order": "Descending" }`. `field` is one of name, type, status, created_at, schedule_start_date, schedule_end_date, client_name, clicks, views, shares. | — |
| locationIds | string | optional | JSON-encoded array of location IDs to include alongside the path location. | — |
| componentIdentifier | string | optional | Filter to posts created by a specific component/integration. | — |
Responses
200A page of post campaigns for the location. `records` is empty when the location has no posts yet.
{ "data": { "rollupSocialPosts": { "records": [ { "id": "U29jaWFsUG9zdDo0NDEyMg==", "name": "Summer Hours Update", "status": "SUCCESS", "type": "ANNOUNCEMENT", "createdAt": "2026-06-28", "scheduledStartDate": "2026-06-28", "scheduledEndDate": "2026-07-28", "views": 128, "clicks": 14, "shares": 0, "reactions": 3, "comments": 1, "sites": ["GOOGLE"], "message": [ { "site": "GOOGLE", "message": "We have extended our summer hours! Open until 9pm on weekdays." } ], "cta": [ { "type": { "value": "LEARN_MORE", "label": "Learn more" }, "url": "https://jennyhome.example/hours", "site": "GOOGLE", "tinyUrl": "https://tiny.cc/jh-hours" } ], "contextInfo": null, "mediaUrl": [ { "url": "https://cdn.listingsapi.com/posts/44122/summer.jpg", "site": "GOOGLE", "type": "IMAGE" } ], "publishDetails": [ { "site": "GOOGLE", "status": "PUBLISHED", "createdDate": "2026-06-28", "publishedDate": "2026-06-28", "submissionError": null } ], "postLinks": [ { "site": "GOOGLE", "link": "https://www.google.com/maps/place/?post=44122" } ], "locationIds": [1800289], "clientName": "Jenny Home" } ], "locationDetails": [ { "id": "TG9jYXRpb246MTgwMDI4OQ==", "name": "Jenny Home", "street": "600 Congress Ave, Suite 200", "city": "Austin", "postalCode": "78701", "countryIso": "US", "stateIso": "TX", "stateName": "Texas", "storeId": null } ], "pageInfo": { "totalPages": 1, "hasNextPage": false, "hasPreviousPage": false, "totalRecords": 1 } } }}401Unauthenticated, missing or invalid API key.
429Rate limit exceeded. Retry after the `Retry-After` header value.
Use this endpoint to pull the post history for a single storefront, every announcement, event, and offer campaign that includes the location, with its lifecycle status and per-post engagement counters (views, clicks, reactions).
Use case: pre-campaign audit. Before scheduling a new Google post for Jenny Home, call GET /locations/TG9jYXRpb246MTgwMDI4OQ==/posts to see what is already live, which posts are still SCHEDULED, and how the last announcement performed. Filter to a single kind with filters={"type":"OFFER"} (URL-encoded) to review only running offers.
Gotchas.
- There is no segment parameter. The endpoint returns every post for the location; narrow the result with
filtersrather than by segment. - Pass
locationIdas the base64 cursor (e.g.TG9jYXRpb246MTgwMDI4OQ==) exactly as returned by the list/search endpoints, do not URL-encode it. - Pagination is offset-based: use
pageandperPage, and readpageInfo.totalPages/pageInfo.totalRecordsto know when to stop. The default sort is newest-first; override withsortFields. sortFieldstakes a single object, not an array: sending an array raises a GraphQL validation error (HTTP 400).- Sustained polling can hit the account rate limit (HTTP 429); honor the
Retry-Afterheader.
The records array in the sample above is representative. The live seed location (Jenny Home) currently has no social posts, so a real call returns records: [] with pageInfo.totalRecords: 0.
Related: create posts with POST /posts, fetch one campaign with GET /posts/{postId}, or list bulk (multi-location) campaigns with GET /locations/{locationId}/bulk-posts.
curl -X GET 'https://listingsapi.com/api/v4/locations/<locationId>/posts' \ -H "Authorization: API $LISTINGSAPI_KEY"