Find locations and archive the ones you no longer manage
Search by keyword, resolve store codes and ids in bulk, schedule closed branches for archival at the end of the billing cycle, and reverse a scheduled archive.
Three read endpoints find locations by different keys: a free-text search, a store-code lookup, and an id lookup. Archiving is a scheduled write: the location stays live until the end of the current billing cycle, then stops syncing and stops being billed. Until that moment you can cancel it.
1. Search by keyword
GET /locations/search?query= matches the term against name, street
address, city, and store id, and returns a cursor connection: edges[].node
with pageInfo.endCursor, paged with first and after. Omit query to
page the whole account.
curl "https://listingsapi.com/api/v4/locations/search?query=Acme&first=10" \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "searchLocations": { "edges": [ { "cursor": "TG9jYXRpb246MTgwMDI4OQ==", "node": { "id": "TG9jYXRpb246MTgwMDI4OQ==", "databaseId": 1800289, "name": "Acme Kitchen", "storeId": "ACME-NYC-001", "approved": "APPROVED", "archived": false, "archivalScheduledAt": null } } ], "pageInfo": { "endCursor": "TG9jYXRpb246MTgwMDI4OQ==", "hasNextPage": false, "total": 1 } } }}An empty edges array means nothing matched, which is the check to run
before a create when you are unsure whether a store already exists. Both
SDKs accept fields to restrict the match to name or store_id only.
2. Look up by store code
If your systems key locations by your own store code, resolve them directly
with GET /locations-by-store-codes. The storeCodes parameter is a JSON
array, URL-encoded. Codes with no match are simply absent from the result.
curl -G https://listingsapi.com/api/v4/locations-by-store-codes \--data-urlencode 'storeCodes=["ACME-NYC-001","ACME-NYC-002"]' \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "getLocationsByStoreCodes": [ { "id": "TG9jYXRpb246MTgwMDI4OQ==", "databaseId": 1800289, "storeId": "ACME-NYC-001", "name": "Acme Kitchen", "archived": false } ] }}3. Hydrate a batch of ids
When you already hold base64 ids, from your own store or a webhook payload,
GET /locations-by-ids returns the full record for all of them in one call.
Archived locations resolve too, so read archived and archivedAt to tell
them apart. Unknown ids are dropped silently; compare counts.
curl -G https://listingsapi.com/api/v4/locations-by-ids \--data-urlencode 'ids=["TG9jYXRpb246MTgwMDI4OQ==","TG9jYXRpb246MTgwMDI5MA=="]' \-H "Authorization: API $LISTINGSAPI_KEY"{ "data": { "getLocationsByIds": [ { "id": "TG9jYXRpb246MTgwMDI4OQ==", "databaseId": 1800289, "name": "Acme Kitchen", "archived": false, "archivedAt": null }, { "id": "TG9jYXRpb246MTgwMDI5MA==", "databaseId": 1800290, "name": "Acme Kitchen Brooklyn", "archived": false, "archivedAt": null } ] }}For a server-side slice of the whole account, GET /locations also accepts
a JSON-encoded filter parameter, for example by approval status. See
List all locations.
4. Archive locations you no longer manage
POST /locations/archive takes input.locationIds and returns one result
entry per location. Archiving is scheduled, not immediate: each location
enters ARCHIVE_SCHEDULED, keeps syncing until the current billing cycle
ends, and is archived when the next invoice is generated. From then on it
stops syncing to publishers and stops being billed.
curl -X POST https://listingsapi.com/api/v4/locations/archive \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "locationIds": ["TG9jYXRpb246MTgwMDI4OQ==", "TG9jYXRpb246MTgwMDI5MA=="] }}'{ "data": { "archiveLocations": { "errors": null, "result": [ { "locationId": "TG9jYXRpb246MTgwMDI4OQ==", "status": "ARCHIVE_SCHEDULED", "success": true, "errors": null }, { "locationId": "TG9jYXRpb246MTgwMDI5MA==", "status": "ARCHIVE_SCHEDULED", "success": true, "errors": null } ] } }}Read each entry's success: one bad id does not block the rest of the
batch. While scheduled, the location's archivalScheduledAt field is set on
list and search results. An archived location cannot be updated until it is
reactivated. If webhooks are configured, a
profile.deleted event fires; it is
a soft delete, and there is no hard delete.
5. Cancel a scheduled archival
Before the cycle closes, POST /locations/cancel_archive with the same ids
pulls them back to ACTIVE and billing continues. Once the location is fully
archived this returns 404 for it. Cancelling emits no webhook event.
curl -X POST https://listingsapi.com/api/v4/locations/cancel_archive \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "input": { "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="] } }'{ "data": { "cancelLocationsArchive": { "errors": null, "result": [ { "locationId": "TG9jYXRpb246MTgwMDI4OQ==", "status": "ACTIVE", "success": true, "errors": null } ] } }}Both SDKs require two extra positional arguments, a selection type and a
changedBy identifier, which they send alongside locationIds. The REST
body needs only the ids.
Next steps
- Add a location: the create call, and why
setting
storeIdthere makes step 2 possible. - Update a location: fix details on the locations you found instead of archiving them.
- Search locations, Get locations by store codes, Get locations by IDs, Archive locations, and Cancel scheduled archival: the reference pages.