v1Resources/Duplicate Listings

Duplicate Listings

Detect, review, and resolve duplicate listings across directories.

Returns duplicate listings detected for one location, grouped by publisher, with counts by status.

Get duplicate listings for a location

get/api/v1/listings/duplicates
listings:read
Query parameters
locationIdstringrequired
The location to look up. Required.
clientIdstringoptional
The location's client. Only needed to disambiguate when your key is scoped to specific clients.
statusstring (potential | flagged | deleted | failed)optional
Restrict results to one status: potential, flagged, deleted, or failed. Counts are always returned for every status regardless of this filter.
Response
dataobjectoptional
foundbooleanoptional
Whether the location was found and accessible to this key.
yourListingobjectoptional
This location's own name, address, and phone, for comparison against each duplicate row. Absent when found is false.
namestringoptional
This location's own business name.
addressstringoptional
This location's own address.
phonestringoptional
This location's own phone number.
countsobjectoptional
Counts of duplicate listings for this location, by status.
potentialnumberoptional
Number of duplicates awaiting review.
flaggednumberoptional
Number of duplicates flagged for removal.
deletednumberoptional
Number of duplicates successfully removed.
failednumberoptional
Number of duplicates whose removal attempt failed.
groupsarray of objectoptional
Duplicate listings, grouped by publisher.
publisherIdstringoptional
Identifier of the directory/publisher (its site URL).
publisherNamestringoptional
Display name of the publisher.
originalUrlstringoptional
Live URL of this location's own real listing on this publisher, or null.
rowsarray of objectoptional
The duplicate listings found on this publisher.
idstringoptional
Unique identifier for this duplicate listing row.
businessNamestringoptional
Business name as it appears on the duplicate listing.
businessNameMatchesbooleanoptional
Whether the duplicate's business name matches this location's own name.
addressstringoptional
Street, city, and postal code of the duplicate listing, joined into one string.
addressMatchesbooleanoptional
Whether the duplicate's address matches this location's own address.
phonestringoptional
Phone number as it appears on the duplicate listing.
phoneMatchesbooleanoptional
Whether the duplicate's phone number matches this location's own phone number.
matchScorenumberoptional
Model confidence, 0–1, that this is the same business as the real listing, or null if unscored.
duplicateUrlstringoptional
Live URL of the duplicate listing, or null.
statusstring (potential | flagged | deleted | failed)optional
One of: potential, flagged, deleted, failed.
Errors
400The request is missing a required parameter or is otherwise malformed.
401Missing, invalid, expired, or revoked API key.
403The key lacks the required scope, or isn't authorized for this client/location.
404The resource wasn't found, or doesn't belong to your agency.
429Too many requests. Retry after the number of seconds in the Retry-After header.
get/api/v1/listings/duplicates
Your API key
locationId *
clientId
status
{
  "data": {
    "found": true,
    "yourListing": {
      "name": "Acme Dental — Downtown",
      "address": "123 Main St, Austin, TX 78701",
      "phone": "+15125551234"
    },
    "counts": {
      "potential": 2,
      "flagged": 1,
      "deleted": 0,
      "failed": 0
    },
    "groups": [
      {
        "publisherId": "yelp",
        "publisherName": "Yelp",
        "status": "potential",
        "duplicates": [
          {
            "id": "dup_1",
            "name": "Acme Dental Downtown",
            "address": "123 Main St, Austin, TX",
            "phone": "+15125551234",
            "url": "https://yelp.com/biz/acme-dental-downtown",
            "matchScore": 0.92
          }
        ]
      }
    ]
  }
}
v1Resources/Duplicate Listings/getGet the duplicate-listings rollup

Returns an aggregated duplicate-listings summary and a paginated queue across every location of a client, or the whole agency when clientId is omitted. A key scoped to specific clients must always pass a clientId — there is no safe agency-wide default for it.

Get the duplicate-listings rollup

get/api/v1/listings/duplicates/rollup
listings:read
Query parameters
clientIdstringoptional
Restrict the rollup to one client. Required when your key is scoped to specific clients.
filterstring (potential | flagged | deleted | failed)optional
Restrict the queue to one status: potential, flagged, deleted, or failed.
bandstring (high | med | low)optional
Restrict the queue to one confidence band: high, med, or low.
publisherSiteIdintegeroptional
Restrict the queue to one publisher, by its numeric site id (see publisherSites in the response).
locationIdstringoptional
Restrict the queue to one location.
tagsstringoptional
Comma-separated list of internal location tags. Only duplicates on locations carrying at least one of these tags are included.
searchstringoptional
Free-text search across the queue's business name, address, and phone.
sortstring (confidence | detected | lastSynced)optional
Sort order for the queue: confidence (highest match score first), detected (most recently detected first), or lastSynced (most recently seen first). Defaults to confidence.
pageintegeroptional
Page number for the queue, starting at 1. Defaults to 1.
perPageintegeroptional
Rows per page for the queue, 1–100. Defaults to 25.
Response
dataobjectoptional
summaryobjectoptional
Aggregated duplicate-listings summary across the requested scope.
potentialTotalnumberoptional
Total number of potential (not yet resolved) duplicates in scope.
locationsAffectednumberoptional
Number of distinct locations with at least one potential duplicate.
bandsobjectoptional
Potential-duplicate counts broken out by confidence band.
highnumberoptional
Count of potential duplicates with a high-confidence match score.
mednumberoptional
Count of potential duplicates with a medium-confidence match score.
lownumberoptional
Count of potential duplicates with a low or unscored match score.
topPublishersarray of objectoptional
Up to 5 publishers with the most potential duplicates, worst offenders first.
publisherIdstringoptional
Identifier of the directory/publisher (its site URL).
publisherNamestringoptional
Display name of the publisher.
countnumberoptional
Number of potential duplicates on this publisher.
publisherSitesarray of objectoptional
Every publisher with a visible duplicate in this scope — the full option list, unlike topPublishers which is capped at 5.
siteIdnumberoptional
Numeric site id for this publisher, usable as the rollup's or resolve's publisherSiteId filter.
publisherIdstringoptional
Identifier of the directory/publisher (its site URL).
publisherNamestringoptional
Display name of the publisher.
queueobjectoptional
The paginated, filterable list of individual duplicate rows across the scope's locations.
rowsarray of objectoptional
The duplicate rows on the current page.
idstringoptional
Unique identifier for this duplicate listing row.
locationIdstringoptional
ID of the location this duplicate belongs to.
locationNamestringoptional
Name of the location this duplicate belongs to.
citystringoptional
City of the location this duplicate belongs to, or null.
locationStreetstringoptional
Street address of the location this duplicate belongs to.
locationStatestringoptional
State or region of the location this duplicate belongs to.
locationPostalCodestringoptional
Postal code of the location this duplicate belongs to.
publisherIdstringoptional
Identifier of the directory/publisher (its site URL).
publisherNamestringoptional
Display name of the publisher.
businessNamestringoptional
Business name as it appears on the duplicate listing.
businessNameMatchesbooleanoptional
Whether the duplicate's business name matches this location's own name.
addressstringoptional
Street, city, and postal code of the duplicate listing, joined into one string.
addressMatchesbooleanoptional
Whether the duplicate's address matches this location's own address.
phonestringoptional
Phone number as it appears on the duplicate listing.
phoneMatchesbooleanoptional
Whether the duplicate's phone number matches this location's own phone number.
matchScorenumberoptional
Model confidence, 0–1, that this is the same business as the real listing, or null if unscored.
bandstring (high | med | low)optional
Confidence band for this row's match score: high, med, or low.
statusstring (potential | flagged | deleted | failed)optional
One of: potential, flagged, deleted, failed.
duplicateUrlstringoptional
Live URL of the duplicate listing, or null.
originalUrlstringoptional
Live URL of this location's own real listing on this publisher, or null.
detectedAtstringoptional
When this duplicate was first detected, as an ISO 8601 timestamp.
lastSyncedAtstringoptional
When this duplicate was last seen during a scan, as an ISO 8601 timestamp.
yourNamestringoptional
The owning location's own business name, for comparison.
yourAddressstringoptional
The owning location's own address, for comparison.
yourPhonestringoptional
The owning location's own phone number, for comparison.
tagsarray of stringoptional
The owning location's internal tags.
totalnumberoptional
Total number of rows matching the current filter, across all pages.
pagenumberoptional
Current page number.
perPagenumberoptional
Rows per page.
Errors
401Missing, invalid, expired, or revoked API key.
403The key lacks the required scope, or isn't authorized for this client/location.
429Too many requests. Retry after the number of seconds in the Retry-After header.
get/api/v1/listings/duplicates/rollup
Your API key
clientId
filter
band
publisherSiteId
locationId
tags
search
sort
page
perPage
{
  "data": {
    "summary": {
      "potentialTotal": 14,
      "locationsAffected": 6,
      "bands": {
        "high": 4,
        "med": 7,
        "low": 3
      },
      "topPublishers": [
        {
          "publisherId": "yelp",
          "publisherName": "Yelp",
          "count": 6
        }
      ],
      "publisherSites": [
        {
          "id": "yelp",
          "name": "Yelp"
        }
      ]
    },
    "queue": {
      "rows": [
        {
          "id": "dup_1",
          "locationId": "loc_456",
          "locationName": "Acme Dental — Downtown",
          "publisherId": "yelp",
          "publisherName": "Yelp",
          "name": "Acme Dental Downtown",
          "matchScore": 0.92,
          "status": "potential"
        }
      ],
      "total": 14,
      "page": 1,
      "perPage": 25
    }
  }
}
v1Resources/Duplicate Listings/postResolve duplicate listings

Flags duplicate listings for removal, or dismisses them, either by an explicit list of duplicateListingIds or by a filter matching the same shape as the rollup queue. Filter-mode runs as a single bulk update scoped to the intersection of the filter's own statuses and the action's eligible source statuses — it can never reach rows outside what that filter would show. Flagging does not remove the listing itself; it queues the removal request, which a background job carries out against the publisher.

Resolve duplicate listings

post/api/v1/listings/duplicates/resolve
listings:write
Request body
actionstring (flag | dismiss)required
flag (request removal from the publisher) or dismiss (mark as not a duplicate).
duplicateListingIdsarray of stringoptional
Explicit ids to resolve, up to 1000. Mutually exclusive with filter.
filterobjectoptional
Resolve every eligible row matching this filter instead of naming ids explicitly. A key scoped to specific clients must also pass clientId when using filter mode.
filterstring (potential | flagged | deleted | failed)optional
Restrict to one status: potential, flagged, deleted, or failed.
bandstring (high | med | low)optional
Restrict to one confidence band: high, med, or low.
publisherSiteIdintegeroptional
Restrict to one publisher, by its numeric site id.
locationIdstringoptional
Restrict to one location.
searchstringoptional
Free-text search across business name, address, and phone.
clientIdstringoptional
Required when your key is scoped to specific clients and you're using filter mode (id-mode is self-limiting per id and doesn't need this).
Response
dataobjectoptional
updatednumberoptional
Number of duplicate listings that transitioned to the new status.
skippedarray of stringoptional
Requested ids that did NOT transition — not found, not owned by your agency/client, or not in an eligible source status. Always empty in filter mode.
Errors
400The request is missing a required parameter or is otherwise malformed.
401Missing, invalid, expired, or revoked API key.
403The key lacks the required scope, or isn't authorized for this client/location.
429Too many requests. Retry after the number of seconds in the Retry-After header.
post/api/v1/listings/duplicates/resolve
Your API key
Request body*
{
  "data": {
    "updated": 3,
    "skipped": []
  }
}