Check listing status and get live links
Read every publisher's sync status for a location, collect the live listing URLs, summarize coverage, check voice assistants, and get notified by webhook instead of polling.
Once a location exists, one listing per publisher in your plan is submitted automatically. This guide shows how to read where each one stands, pull the URLs of the listings that are live, and stop polling once webhooks are set up.
1. Fetch the premium listings for a location
GET /locations/{locationId}/listings/premium returns one record per premium
publisher in the plan. It is a plain array, not a paginated list. The sibling
route /listings/additional returns the free directories with the same
shape; there is no listingType query parameter.
curl https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/listings/premium \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "listingsForLocation": [ { "site": { "name": "Google Maps", "url": "maps.google.com" }, "syncStatus": "REQUIRING_ACTION", "displayStatus": "Connect your account to sync the listing", "actionRequired": true, "listingUrl": null, "syncIssue": null, "lastUpdate": "2026-07-06T18:33:28Z" }, { "site": { "name": "BeLocalFocussed", "url": "belocalfocussed.com" }, "syncStatus": "SYNCED", "displayStatus": "Synced", "actionRequired": false, "listingUrl": "https://belocalfocussed.com/jenny-home-26x0ffkd0e", "syncIssue": null, "lastUpdate": "2026-07-06T18:33:30Z" } ] }}Each row pairs a site with a machine-readable syncStatus and a
human-readable displayStatus. lastUpdate tells you when the row last
changed, which is useful for spotting a submission that has stalled.
2. Read the status of each publisher
syncStatus is the field to branch on. displayStatus is the text to show a
person, and syncIssue carries the publisher's reason when there is one.
Google Maps and Facebook stay at REQUIRING_ACTION until that publisher's
account is connected: a Google Business Profile for Google Maps and a Facebook
Page for Facebook. That is expected for a new location, not a fault.
Apple Maps does not require a connection. If the owner has not connected a verified Apple Business organization account, ListingsAPI submits the location through its own Apple Business Connect account, and Apple verifies the submission before it publishes. See Connect Apple Business Connect.
3. Collect the live links
listingUrl is only set on live rows. Filter to SYNCED (and COMPLETED)
and keep the URL with the site name so you can render a "see it live" list or
store it against your own record.
curl -s https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/listings/premium \-H "Authorization: API $LISTINGSAPI_KEY" \| jq '[.data.listingsForLocation[] | select(.listingUrl != null) | {site: .site.name, url: .listingUrl}]'A SYNCED row with a null listingUrl does happen: some directories do not
expose a public page URL. Treat the status as authoritative and the link as
optional.
4. Build a coverage summary
Counting rows by syncStatus gives a one-line health figure per location:
how many publishers are live, how many are still in flight, and how many are
blocked. This is the number to put on a dashboard.
curl -s https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/listings/premium \-H "Authorization: API $LISTINGSAPI_KEY" \| jq '.data.listingsForLocation | group_by(.syncStatus) | map({status: .[0].syncStatus, count: length})'Run this across many locations by paging GET /locations and calling the
premium endpoint once per location. Each call counts against your rate limit,
so leave a gap between them and honor Retry-After on a 429. Find and fix listing errors shows the
loop as an account-wide sweep.
5. Check voice assistants
Voice assistants (Google Assistant, Alexa, Siri, Cortana, Bixby) have their own
endpoint, GET /locations/{locationId}/voice-assistants, with a smaller
status set. Google Assistant depends on the Google connection, so a location
without one needs attention here too. Siri results come from the location's
Apple Maps listing.
curl https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/voice-assistants \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "voiceAssistantsForLocation": [ { "voiceIdentifier": "GOOGLE_ASSISTANT", "name": "Google Assistant", "syncStatus": "REQUIRING_ACTION", "actionRequired": true, "syncIssue": null, "errors": [] }, { "voiceIdentifier": "SIRI", "name": "Siri", "syncStatus": "IN_PROGRESS", "actionRequired": false, "syncIssue": null, "errors": [] } ] }}There is no live link for a voice assistant; LIVE is the end state.
6. Receive webhook events instead of polling
If you have a webhook URL configured at /dashboard/webhooks, the
listing.submission event fires
each time a publisher submission for one location reaches a terminal state.
It carries status (success, incomplete, or canceled), the site, and
live_link on success, which is the same URL you collected in step 3.
import base64 def handle(payload: dict) -> None: if payload["event"] != "listing.submission": return data = payload["data"] # "TG9jYXRpb246Mjc5Mzgx" -> "Location:279381" global_id = base64.b64decode(data["location_id"]).decode() database_id = int(global_id.split(":")[1]) site = data["site"]["name"] status = payload["status"] if status == "success": live_link = payload.get("live_link") save_live_link(database_id, site, live_link) elif status == "incomplete": flag_for_review(database_id, site, payload.get("error_message"))Respond with 200 within 5 seconds and do the work afterwards; there are no
retries. For the receiver skeleton and signature check, see
React to events with webhooks.
Next steps
- Find and fix listing errors: turn
REQUIRING_ACTIONandFAILEDrows into fixes. - Connect Google and import locations: connect the Google Business Profile that Google Maps and Google Assistant use.
- Connect Apple Business Connect: publish Apple Maps through the owner's verified Apple Business account.
- Find and suppress duplicate listings: the other half of listing health.
- Reference: Get premium listings, Get voice assistant listings, Event reference.