Businesses

Browse the business dataset

Server-side filtered, keyset-paginated view of the shared business dataset. Contact values (phone, email, website) are never returned for rows you do not own — only hasPhone/hasEmail/hasWebsite presence flags. Unlock a row to get the values. Pass cursor from the previous response to page; never build one yourself. Requires the business:read scope when called with a scoped key.

GET/v1/businesses

Server-side filtered, keyset-paginated view of the shared business dataset. Contact values (phone, email, website) are never returned for rows you do not own — only hasPhone/hasEmail/hasWebsite presence flags. Unlock a row to get the values. Pass cursor from the previous response to page; never build one yourself. Requires the business:read scope when called with a scoped key.

AuthorizationBearer <token>

Pass Authorization: Bearer mapleads_xxx.

In: header

Query Parameters

provider?array<>

Source maps to keep. Repeat the parameter or comma-separate. Omit to include all three — there is no default map. The same business can appear once per map; those are separate rows with separate identifiers, not duplicates.

q?string

Free text over name and address.

country?string

Exact country match.

locality?string

Exact city/locality match.

category?string

Row has this category.

minRating?number

Only rows rated at least this.

hasPhone?boolean

Three-state. true keeps only rows that have a phone number, false keeps only rows that have none, and omitting the parameter does not filter on it. Any other value is a 400 — a typo must not silently widen the result set.

hasWebsite?boolean

Three-state. true keeps only rows that have a website, false keeps only rows that have none, and omitting the parameter does not filter on it. Any other value is a 400 — a typo must not silently widen the result set.

hasEmail?boolean

Three-state. true keeps only rows that have an email address, false keeps only rows that have none, and omitting the parameter does not filter on it. Any other value is a 400 — a typo must not silently widen the result set.

limit?integer

Rows per page (default 50, max 200).

cursor?string

Opaque keyset cursor from the previous response. The way to walk the whole dataset: cost per page stays flat however deep you go. Mutually exclusive with page.

page?integer

1-based page number, for a numbered pager. Costs an offset, so it is capped at 500; past that the response is a 400 naming cursor as the way to go further. Mutually exclusive with cursor. Only when this is set does the response carry page, because counting matches is not free and is not done unasked.

Range1 <= value <= 500
owned?boolean

Three-state, like the presence filters. true keeps only rows this account already has, false keeps only rows it does not, and omitting the parameter does not filter on it. The web app sends false by default — unlocking is the only thing on offer here — but it is a default, not a rule: a row stays reachable straight after it is unlocked.

emailStatus?array<>

Keep rows with at least one email in any of these states. Any-match, not all-match: a business with one info@ and one real person belongs in a deliverable search. An unrecognised value is a 400 rather than a silently ignored filter, because ignoring it returns far more rows than were asked for.

Response Body

application/json

curl -X GET "https://example.com/v1/businesses"
{  "data": [    {      "provider": "google",      "providerBusinessId": "string",      "name": "string",      "cid": "string",      "placeId": "string",      "locality": "string",      "country": "string",      "categories": [        "string"      ],      "rating": 0,      "reviewCount": 0,      "hasPhone": true,      "hasWebsite": true,      "hasEmail": true,      "owned": true,      "observedAt": "2019-08-24T14:15:22Z",      "emailCount": 0,      "emailStatuses": [        "deliverable"      ],      "credits": 0    }  ],  "nextCursor": "string",  "page": {    "number": 0,    "size": 0,    "total": 0,    "totalIsExact": true,    "maxPage": 0  }}